xref: /onnv-gate/usr/src/uts/common/os/lgrp_topo.c (revision 12762:9c71588c0d0e)
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
55608Srv207048  * Common Development and Distribution License (the "License").
65608Srv207048  * 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*12762SEthindra.Ramamurthy@Sun.COM  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate  * lgroup topology
270Sstevel@tonic-gate  */
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <sys/cpupart.h>
300Sstevel@tonic-gate #include <sys/lgrp.h>
310Sstevel@tonic-gate #include <sys/promif.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #define	LGRP_TOPO_LEVELS	4	/* default height limit */
360Sstevel@tonic-gate #define	LGRP_TOPO_LEVELS_MAX	4	/* max height limit */
370Sstevel@tonic-gate 
380Sstevel@tonic-gate 
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate  * Only collapse lgroups which have same latency (and resources)
410Sstevel@tonic-gate  */
420Sstevel@tonic-gate int		lgrp_collapse_equidist = 1;
430Sstevel@tonic-gate 
440Sstevel@tonic-gate int		lgrp_collapse_off = 1;	/* disable collapsing of duplicates */
450Sstevel@tonic-gate 
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate  * Height to limit lgroup topology
480Sstevel@tonic-gate  */
490Sstevel@tonic-gate unsigned int	lgrp_topo_levels = LGRP_TOPO_LEVELS;
500Sstevel@tonic-gate 
510Sstevel@tonic-gate int		lgrp_split_off = 1;	/* disable splitting lgroups */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #ifdef	DEBUG
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate  * Debugging output
560Sstevel@tonic-gate  * - 0: off
570Sstevel@tonic-gate  * - >0: on and bigger means more
580Sstevel@tonic-gate  */
590Sstevel@tonic-gate int	lgrp_topo_debug = 0;
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 
620Sstevel@tonic-gate void
klgrpset_print(klgrpset_t lgrpset)630Sstevel@tonic-gate klgrpset_print(klgrpset_t lgrpset)
640Sstevel@tonic-gate {
650Sstevel@tonic-gate 	int	i;
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	prom_printf("0x%llx(", (u_longlong_t)lgrpset);
690Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++)
700Sstevel@tonic-gate 		if (klgrpset_ismember(lgrpset, i))
710Sstevel@tonic-gate 			prom_printf("%d ", i);
720Sstevel@tonic-gate 	prom_printf(")\n");
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 
760Sstevel@tonic-gate void
lgrp_rsets_print(char * string,klgrpset_t * rsets)770Sstevel@tonic-gate lgrp_rsets_print(char *string, klgrpset_t *rsets)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	int	i;
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	prom_printf("%s\n", string);
820Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
830Sstevel@tonic-gate 		klgrpset_print(rsets[i]);
840Sstevel@tonic-gate }
850Sstevel@tonic-gate #endif	/* DEBUG */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate 
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate  * Add "from" lgroup resources to "to" lgroup resources
900Sstevel@tonic-gate  */
910Sstevel@tonic-gate void
lgrp_rsets_add(klgrpset_t * from,klgrpset_t * to)920Sstevel@tonic-gate lgrp_rsets_add(klgrpset_t *from, klgrpset_t *to)
930Sstevel@tonic-gate {
940Sstevel@tonic-gate 	int	i;
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
970Sstevel@tonic-gate 		klgrpset_or(to[i], from[i]);
980Sstevel@tonic-gate }
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate  * Copy "from" lgroup resources to "to" lgroup resources
1030Sstevel@tonic-gate  */
1040Sstevel@tonic-gate void
lgrp_rsets_copy(klgrpset_t * from,klgrpset_t * to)1050Sstevel@tonic-gate lgrp_rsets_copy(klgrpset_t *from, klgrpset_t *to)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate 	int	i;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1100Sstevel@tonic-gate 		to[i] = from[i];
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate /*
1150Sstevel@tonic-gate  * Delete given lgroup ID from lgroup resource set of specified lgroup
1160Sstevel@tonic-gate  * and its ancestors if "follow_parent" is set
1170Sstevel@tonic-gate  */
1180Sstevel@tonic-gate void
lgrp_rsets_delete(lgrp_t * lgrp,lgrp_id_t lgrpid,int follow_parent)1190Sstevel@tonic-gate lgrp_rsets_delete(lgrp_t *lgrp, lgrp_id_t lgrpid, int follow_parent)
1200Sstevel@tonic-gate {
1210Sstevel@tonic-gate 	int	i;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	while (lgrp != NULL) {
1240Sstevel@tonic-gate 		for (i = 0; i < LGRP_RSRC_COUNT; i++)
1250Sstevel@tonic-gate 			klgrpset_del(lgrp->lgrp_set[i], lgrpid);
1260Sstevel@tonic-gate 		if (!follow_parent)
1270Sstevel@tonic-gate 			break;
1280Sstevel@tonic-gate 		lgrp = lgrp->lgrp_parent;
1290Sstevel@tonic-gate 	}
1300Sstevel@tonic-gate }
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate  * Return whether given lgroup resource set empty
1350Sstevel@tonic-gate  */
1360Sstevel@tonic-gate int
lgrp_rsets_empty(klgrpset_t * rset)1370Sstevel@tonic-gate lgrp_rsets_empty(klgrpset_t *rset)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	int	i;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1420Sstevel@tonic-gate 		if (!klgrpset_isempty(rset[i]))
1430Sstevel@tonic-gate 			return (0);
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 	return (1);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate  * Return whether given lgroup resource sets are same
1510Sstevel@tonic-gate  */
1520Sstevel@tonic-gate int
lgrp_rsets_equal(klgrpset_t * rset1,klgrpset_t * rset2)1530Sstevel@tonic-gate lgrp_rsets_equal(klgrpset_t *rset1, klgrpset_t *rset2)
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate 	int	i;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1580Sstevel@tonic-gate 		if (rset1[i] != rset2[i])
1590Sstevel@tonic-gate 			return (0);
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	return (1);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate /*
1660Sstevel@tonic-gate  * Return whether specified lgroup ID is in given lgroup resource set
1670Sstevel@tonic-gate  */
1680Sstevel@tonic-gate int
lgrp_rsets_member(klgrpset_t * rset,lgrp_id_t lgrpid)1690Sstevel@tonic-gate lgrp_rsets_member(klgrpset_t *rset, lgrp_id_t lgrpid)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate 	int	i;
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1740Sstevel@tonic-gate 		if (klgrpset_ismember(rset[i], lgrpid))
1750Sstevel@tonic-gate 			return (1);
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	return (0);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate /*
1820Sstevel@tonic-gate  * Return whether specified lgroup ID is in all lgroup resources
1830Sstevel@tonic-gate  */
1840Sstevel@tonic-gate int
lgrp_rsets_member_all(klgrpset_t * rset,lgrp_id_t lgrpid)1850Sstevel@tonic-gate lgrp_rsets_member_all(klgrpset_t *rset, lgrp_id_t lgrpid)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	int	i;
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1900Sstevel@tonic-gate 		if (!klgrpset_ismember(rset[i], lgrpid))
1910Sstevel@tonic-gate 			return (0);
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	return (1);
1940Sstevel@tonic-gate }
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate  * Replace resources for given lgroup with specified resources at given
1990Sstevel@tonic-gate  * latency and shift its old resources to its parent and its parent's resources
2000Sstevel@tonic-gate  * to its parent, etc. until root lgroup reached
2010Sstevel@tonic-gate  */
2020Sstevel@tonic-gate void
lgrp_rsets_replace(klgrpset_t * rset,int latency,lgrp_t * lgrp,int shift)2030Sstevel@tonic-gate lgrp_rsets_replace(klgrpset_t *rset, int latency, lgrp_t *lgrp, int shift)
2040Sstevel@tonic-gate {
2050Sstevel@tonic-gate 	lgrp_t		*cur;
2060Sstevel@tonic-gate 	int		lat_new;
2070Sstevel@tonic-gate 	int		lat_saved;
2080Sstevel@tonic-gate 	klgrpset_t	rset_new[LGRP_RSRC_COUNT];
2090Sstevel@tonic-gate 	klgrpset_t	rset_saved[LGRP_RSRC_COUNT];
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 	cur = lgrp;
2120Sstevel@tonic-gate 	lat_saved = latency;
2130Sstevel@tonic-gate 	lgrp_rsets_copy(rset, rset_saved);
2140Sstevel@tonic-gate 	while (cur && cur != lgrp_root) {
2150Sstevel@tonic-gate 		/*
2160Sstevel@tonic-gate 		 * Save current resources and latency to insert in parent and
2170Sstevel@tonic-gate 		 * then replace with new resources and latency
2180Sstevel@tonic-gate 		 */
2190Sstevel@tonic-gate 		lgrp_rsets_copy(rset_saved, rset_new);
2200Sstevel@tonic-gate 		lgrp_rsets_copy(cur->lgrp_set, rset_saved);
2210Sstevel@tonic-gate 		lgrp_rsets_copy(rset_new, cur->lgrp_set);
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 		lat_new = lat_saved;
2240Sstevel@tonic-gate 		lat_saved = cur->lgrp_latency;
2250Sstevel@tonic-gate 		cur->lgrp_latency = lat_new;
2260Sstevel@tonic-gate 		if (!shift)
2270Sstevel@tonic-gate 			break;
2280Sstevel@tonic-gate 		cur = cur->lgrp_parent;
2290Sstevel@tonic-gate 	}
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate /*
2340Sstevel@tonic-gate  * Set "to" lgroup resource set with given lgroup ID
2350Sstevel@tonic-gate  */
2360Sstevel@tonic-gate void
lgrp_rsets_set(klgrpset_t * to,lgrp_id_t lgrpid)2370Sstevel@tonic-gate lgrp_rsets_set(klgrpset_t *to, lgrp_id_t lgrpid)
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate 	klgrpset_t	from;
2400Sstevel@tonic-gate 	int		i;
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	klgrpset_clear(from);
2430Sstevel@tonic-gate 	klgrpset_add(from, lgrpid);
2440Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++) {
2450Sstevel@tonic-gate 		klgrpset_clear(to[i]);
2460Sstevel@tonic-gate 		klgrpset_or(to[i], from);
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate  * Delete any ancestors of given child lgroup which don't have any other
2530Sstevel@tonic-gate  * children
2540Sstevel@tonic-gate  */
2550Sstevel@tonic-gate int
lgrp_ancestor_delete(lgrp_t * child,klgrpset_t * changed)2560Sstevel@tonic-gate lgrp_ancestor_delete(lgrp_t *child, klgrpset_t *changed)
2570Sstevel@tonic-gate {
2580Sstevel@tonic-gate 	int		count;
2590Sstevel@tonic-gate 	lgrp_t		*current;
2600Sstevel@tonic-gate 	lgrp_id_t	lgrpid;
2610Sstevel@tonic-gate 	lgrp_t		*parent;
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate #ifdef	DEBUG
2640Sstevel@tonic-gate 	if (lgrp_topo_debug > 1) {
2650Sstevel@tonic-gate 		prom_printf("lgrp_ancestor_delete(0x%p[%d],0x%p)\n",
2667632SNick.Todd@Sun.COM 		    (void *)child, child->lgrp_id, (void *)changed);
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate #endif	/* DEBUG */
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 	count = 0;
2710Sstevel@tonic-gate 	if (changed)
2720Sstevel@tonic-gate 		klgrpset_clear(*changed);
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 	/*
2750Sstevel@tonic-gate 	 * Visit ancestors, decrement child count for each, and remove any
2760Sstevel@tonic-gate 	 * that don't have any children left until we reach an ancestor that
2770Sstevel@tonic-gate 	 * has multiple children
2780Sstevel@tonic-gate 	 */
2790Sstevel@tonic-gate 	current = child;
2800Sstevel@tonic-gate 	parent = child->lgrp_parent;
2810Sstevel@tonic-gate 	lgrpid = current->lgrp_id;
2820Sstevel@tonic-gate 	while (parent != NULL) {
2830Sstevel@tonic-gate #ifdef	DEBUG
2840Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
2850Sstevel@tonic-gate 			prom_printf("lgrp_ancestor_delete: parent %d,"
2860Sstevel@tonic-gate 			    " current %d\n",
2870Sstevel@tonic-gate 			    parent->lgrp_id, lgrpid);
2880Sstevel@tonic-gate #endif	/* DEBUG */
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_leaves, lgrpid);
2910Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_children, lgrpid);
2920Sstevel@tonic-gate 		parent->lgrp_childcnt--;
2930Sstevel@tonic-gate 		if (changed)
2940Sstevel@tonic-gate 			klgrpset_add(*changed, parent->lgrp_id);
2950Sstevel@tonic-gate 		count++;
2960Sstevel@tonic-gate 		if (parent->lgrp_childcnt != 0)
2970Sstevel@tonic-gate 			break;
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 		current = parent;
3000Sstevel@tonic-gate 		parent = current->lgrp_parent;
3010Sstevel@tonic-gate 		lgrpid = current->lgrp_id;
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate #ifdef	DEBUG
3040Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
3050Sstevel@tonic-gate 			prom_printf("lgrp_ancestor_delete: destroy"
3060Sstevel@tonic-gate 			    " lgrp %d at 0x%p\n",
3077632SNick.Todd@Sun.COM 			    current->lgrp_id, (void *)current);
3080Sstevel@tonic-gate #endif	/* DEBUG */
3090Sstevel@tonic-gate 		lgrp_destroy(current);
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate #ifdef	DEBUG
3130Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
3140Sstevel@tonic-gate 		prom_printf("lgrp_ancestor_delete: changed %d lgrps: 0x%llx\n",
3150Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
3160Sstevel@tonic-gate #endif	/* DEBUG */
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate 	return (count);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate  * Consolidate lgrp1 into lgrp2
3240Sstevel@tonic-gate  */
3250Sstevel@tonic-gate int
lgrp_consolidate(lgrp_t * lgrp1,lgrp_t * lgrp2,klgrpset_t * changed)3260Sstevel@tonic-gate lgrp_consolidate(lgrp_t *lgrp1, lgrp_t *lgrp2, klgrpset_t *changed)
3270Sstevel@tonic-gate {
3280Sstevel@tonic-gate 	klgrpset_t	changes;
3290Sstevel@tonic-gate 	lgrp_t		*child;
3300Sstevel@tonic-gate 	int		count;
3310Sstevel@tonic-gate 	int		i;
3320Sstevel@tonic-gate 	lgrp_t		*parent;
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/*
3350Sstevel@tonic-gate 	 * Leaf lgroups should never need to be consolidated
3360Sstevel@tonic-gate 	 */
3370Sstevel@tonic-gate 	if (lgrp1 == NULL || lgrp2 == NULL || lgrp1->lgrp_childcnt < 1 ||
3380Sstevel@tonic-gate 	    lgrp2->lgrp_childcnt < 1)
3390Sstevel@tonic-gate 		return (0);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate #ifdef	DEBUG
3420Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
3430Sstevel@tonic-gate 		prom_printf("lgrp_consolidate(0x%p[%d],0x%p[%d],0x%p)\n",
3447632SNick.Todd@Sun.COM 		    (void *)lgrp1, lgrp1->lgrp_id, (void *)lgrp2,
3457632SNick.Todd@Sun.COM 		    lgrp2->lgrp_id, (void *)changed);
3460Sstevel@tonic-gate #endif	/* DEBUG */
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate 	count = 0;
3490Sstevel@tonic-gate 	if (changed)
3500Sstevel@tonic-gate 		klgrpset_clear(*changed);
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	/*
3530Sstevel@tonic-gate 	 * Lgroup represents resources within certain latency, so need to keep
3540Sstevel@tonic-gate 	 * biggest latency value of lgroups being consolidated
3550Sstevel@tonic-gate 	 */
3560Sstevel@tonic-gate 	if (lgrp1->lgrp_latency > lgrp2->lgrp_latency)
3570Sstevel@tonic-gate 		lgrp2->lgrp_latency = lgrp1->lgrp_latency;
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	/*
3600Sstevel@tonic-gate 	 * Delete ancestors of lgrp1 that don't have any other children
3610Sstevel@tonic-gate 	 */
3620Sstevel@tonic-gate #ifdef	DEBUG
3630Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
3640Sstevel@tonic-gate 		prom_printf("lgrp_consolidate: delete ancestors\n");
3650Sstevel@tonic-gate #endif	/* DEBUG */
3660Sstevel@tonic-gate 	count += lgrp_ancestor_delete(lgrp1, &changes);
3670Sstevel@tonic-gate 	if (changed) {
3680Sstevel@tonic-gate 		klgrpset_or(*changed, changes);
3690Sstevel@tonic-gate 		klgrpset_or(*changed, lgrp1->lgrp_id);
3700Sstevel@tonic-gate 		count++;
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 
3730Sstevel@tonic-gate 	/*
3740Sstevel@tonic-gate 	 * Reparent children lgroups of lgrp1 to lgrp2
3750Sstevel@tonic-gate 	 */
3760Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++) {
3770Sstevel@tonic-gate 		if (i == lgrp2->lgrp_id ||
3780Sstevel@tonic-gate 		    !klgrpset_ismember(lgrp1->lgrp_children, i))
3790Sstevel@tonic-gate 			continue;
3800Sstevel@tonic-gate 		child = lgrp_table[i];
3810Sstevel@tonic-gate 		if (!LGRP_EXISTS(child))
3820Sstevel@tonic-gate 			continue;
3830Sstevel@tonic-gate #ifdef	DEBUG
3840Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
3850Sstevel@tonic-gate 			prom_printf("lgrp_consolidate: reparent "
3860Sstevel@tonic-gate 			    "lgrp %d to lgrp %d\n",
3870Sstevel@tonic-gate 			    child->lgrp_id, lgrp2->lgrp_id);
3880Sstevel@tonic-gate #endif	/* DEBUG */
3890Sstevel@tonic-gate 		klgrpset_or(lgrp2->lgrp_leaves, child->lgrp_leaves);
3900Sstevel@tonic-gate 		klgrpset_add(lgrp2->lgrp_children, child->lgrp_id);
3910Sstevel@tonic-gate 		lgrp2->lgrp_childcnt++;
3920Sstevel@tonic-gate 		child->lgrp_parent = lgrp2;
3930Sstevel@tonic-gate 		if (changed) {
3940Sstevel@tonic-gate 			klgrpset_add(*changed, child->lgrp_id);
3950Sstevel@tonic-gate 			klgrpset_add(*changed, lgrp2->lgrp_id);
3960Sstevel@tonic-gate 		}
3970Sstevel@tonic-gate 		count += 2;
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	/*
4010Sstevel@tonic-gate 	 * Proprogate leaves from lgrp2 to root
4020Sstevel@tonic-gate 	 */
4030Sstevel@tonic-gate 	child = lgrp2;
4040Sstevel@tonic-gate 	parent = child->lgrp_parent;
4050Sstevel@tonic-gate 	while (parent != NULL) {
4060Sstevel@tonic-gate 		klgrpset_or(parent->lgrp_leaves, child->lgrp_leaves);
4070Sstevel@tonic-gate 		if (changed)
4080Sstevel@tonic-gate 			klgrpset_add(*changed, parent->lgrp_id);
4090Sstevel@tonic-gate 		count++;
4100Sstevel@tonic-gate 		child = parent;
4110Sstevel@tonic-gate 		parent = parent->lgrp_parent;
4120Sstevel@tonic-gate 	}
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate #ifdef	DEBUG
4150Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
4160Sstevel@tonic-gate 		prom_printf("lgrp_consolidate: destroy lgrp %d at 0x%p\n",
4177632SNick.Todd@Sun.COM 		    lgrp1->lgrp_id, (void *)lgrp1);
4180Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
4190Sstevel@tonic-gate 		prom_printf("lgrp_consolidate: changed %d lgrps: 0x%llx\n",
4200Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
4210Sstevel@tonic-gate #endif	/* DEBUG */
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	lgrp_destroy(lgrp1);
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	return (count);
4260Sstevel@tonic-gate }
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate /*
4290Sstevel@tonic-gate  * Collapse duplicates of target lgroups given
4300Sstevel@tonic-gate  */
4310Sstevel@tonic-gate int
lgrp_collapse_dups(klgrpset_t target_set,int equidist_only,klgrpset_t * changed)4320Sstevel@tonic-gate lgrp_collapse_dups(klgrpset_t target_set, int equidist_only,
4330Sstevel@tonic-gate     klgrpset_t *changed)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate 	klgrpset_t	changes;
4360Sstevel@tonic-gate 	int		count;
4370Sstevel@tonic-gate 	int		i;
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 	count = 0;
4400Sstevel@tonic-gate 	if (changed)
4410Sstevel@tonic-gate 		klgrpset_clear(*changed);
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	if (lgrp_collapse_off)
4440Sstevel@tonic-gate 		return (0);
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate #ifdef	DEBUG
4470Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
4480Sstevel@tonic-gate 		prom_printf("lgrp_collapse_dups(0x%llx)\n",
4490Sstevel@tonic-gate 		    (u_longlong_t)target_set);
4500Sstevel@tonic-gate #endif	/* DEBUG */
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	/*
4530Sstevel@tonic-gate 	 * Look for duplicates of each target lgroup
4540Sstevel@tonic-gate 	 */
4550Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++) {
4560Sstevel@tonic-gate 		int	j;
4570Sstevel@tonic-gate 		lgrp_t	*keep;
4580Sstevel@tonic-gate 		lgrp_t	*target;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 		target = lgrp_table[i];
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 		/*
4630Sstevel@tonic-gate 		 * Skip to next lgroup if there isn't one here, this is root
4640Sstevel@tonic-gate 		 * or leaf lgroup, or this isn't a target lgroup
4650Sstevel@tonic-gate 		 */
4660Sstevel@tonic-gate 		if (!LGRP_EXISTS(target) ||
4670Sstevel@tonic-gate 		    target == lgrp_root || target->lgrp_childcnt == 0 ||
4680Sstevel@tonic-gate 		    !klgrpset_ismember(target_set, target->lgrp_id))
4690Sstevel@tonic-gate 			continue;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 		/*
4720Sstevel@tonic-gate 		 * Find all lgroups with same resources and latency
4730Sstevel@tonic-gate 		 */
4740Sstevel@tonic-gate #ifdef	DEBUG
4750Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
4760Sstevel@tonic-gate 			prom_printf("lgrp_collapse_dups: find "
4770Sstevel@tonic-gate 			    "dups of lgrp %d at 0x%p\n",
4787632SNick.Todd@Sun.COM 			    target->lgrp_id, (void *)target);
4790Sstevel@tonic-gate #endif	/* DEBUG */
4800Sstevel@tonic-gate 		keep = NULL;
4810Sstevel@tonic-gate 		for (j = 0; j <= lgrp_alloc_max; j++) {
4820Sstevel@tonic-gate 			lgrp_t	*lgrp;
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 			lgrp = lgrp_table[j];
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate 			/*
4870Sstevel@tonic-gate 			 * Skip lgroup if there isn't one here, this is root
4880Sstevel@tonic-gate 			 * lgroup or leaf (which shouldn't have dups), or this
4890Sstevel@tonic-gate 			 * lgroup doesn't have same resources
4900Sstevel@tonic-gate 			 */
4910Sstevel@tonic-gate 			if (!LGRP_EXISTS(lgrp) ||
4920Sstevel@tonic-gate 			    lgrp->lgrp_childcnt == 0 ||
4930Sstevel@tonic-gate 			    !lgrp_rsets_equal(lgrp->lgrp_set,
4940Sstevel@tonic-gate 			    target->lgrp_set) ||
4950Sstevel@tonic-gate 			    (lgrp->lgrp_latency != target->lgrp_latency &&
4960Sstevel@tonic-gate 			    equidist_only))
4970Sstevel@tonic-gate 				continue;
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 			/*
5000Sstevel@tonic-gate 			 * Keep first matching lgroup (but always keep root)
5010Sstevel@tonic-gate 			 * and consolidate other duplicates into it
5020Sstevel@tonic-gate 			 */
5030Sstevel@tonic-gate 			if (keep == NULL) {
5040Sstevel@tonic-gate 				keep = lgrp;
5050Sstevel@tonic-gate #ifdef	DEBUG
5060Sstevel@tonic-gate 				if (lgrp_topo_debug > 1)
5070Sstevel@tonic-gate 					prom_printf("lgrp_collapse_dups: "
5080Sstevel@tonic-gate 					    "keep lgrp %d at 0x%p\n",
5097632SNick.Todd@Sun.COM 					    keep->lgrp_id, (void *)keep);
5100Sstevel@tonic-gate #endif	/* DEBUG */
5110Sstevel@tonic-gate 			} else {
5120Sstevel@tonic-gate 				if (lgrp == lgrp_root) {
5130Sstevel@tonic-gate 					lgrp = keep;
5140Sstevel@tonic-gate 					keep = lgrp_root;
5150Sstevel@tonic-gate 				}
5160Sstevel@tonic-gate #ifdef	DEBUG
5170Sstevel@tonic-gate 				if (lgrp_topo_debug > 0)
5180Sstevel@tonic-gate 					prom_printf("lgrp_collapse_dups:"
5190Sstevel@tonic-gate 					    " consolidate lgrp %d at 0x%p"
5200Sstevel@tonic-gate 					    " into lgrp %d at 0x%p\n",
5217632SNick.Todd@Sun.COM 					    lgrp->lgrp_id, (void *)lgrp,
5227632SNick.Todd@Sun.COM 					    keep->lgrp_id, (void *)keep);
5230Sstevel@tonic-gate #endif	/* DEBUG */
5240Sstevel@tonic-gate 				count += lgrp_consolidate(lgrp, keep,
5250Sstevel@tonic-gate 				    &changes);
5260Sstevel@tonic-gate 				if (changed)
5270Sstevel@tonic-gate 					klgrpset_or(*changed, changes);
5280Sstevel@tonic-gate 			}
5290Sstevel@tonic-gate 		}
5300Sstevel@tonic-gate 	}
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate #ifdef	DEBUG
5330Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
5340Sstevel@tonic-gate 		prom_printf("lgrp_collapse_dups: changed %d lgrps: 0x%llx\n",
5350Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
5360Sstevel@tonic-gate #endif	/* DEBUG */
5370Sstevel@tonic-gate 
5380Sstevel@tonic-gate 	return (count);
5390Sstevel@tonic-gate }
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 
5420Sstevel@tonic-gate /*
5430Sstevel@tonic-gate  * Create new parent lgroup with given latency and resources for
5440Sstevel@tonic-gate  * specified child lgroup, and insert it into hierarchy
5450Sstevel@tonic-gate  */
5460Sstevel@tonic-gate int
lgrp_new_parent(lgrp_t * child,int latency,klgrpset_t * rset,klgrpset_t * changed)5470Sstevel@tonic-gate lgrp_new_parent(lgrp_t *child, int latency, klgrpset_t *rset,
5480Sstevel@tonic-gate     klgrpset_t *changed)
5490Sstevel@tonic-gate {
5500Sstevel@tonic-gate 	int	count;
5510Sstevel@tonic-gate 	lgrp_t	*new;
5520Sstevel@tonic-gate 	lgrp_t	*old;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	count = 0;
5550Sstevel@tonic-gate 	if (changed)
5560Sstevel@tonic-gate 		klgrpset_clear(*changed);
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	/*
5590Sstevel@tonic-gate 	 * Create lgroup and set its latency and resources
5600Sstevel@tonic-gate 	 */
5610Sstevel@tonic-gate 	new = lgrp_create();
5620Sstevel@tonic-gate 	new->lgrp_latency = latency;
5630Sstevel@tonic-gate 	lgrp_rsets_add(rset, new->lgrp_set);
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 	/*
5660Sstevel@tonic-gate 	 * Insert new lgroup into hierarchy
5670Sstevel@tonic-gate 	 */
5680Sstevel@tonic-gate 	old = child->lgrp_parent;
5690Sstevel@tonic-gate 	new->lgrp_parent = old;
5700Sstevel@tonic-gate 	klgrpset_add(new->lgrp_children, child->lgrp_id);
5710Sstevel@tonic-gate 	new->lgrp_childcnt++;
5720Sstevel@tonic-gate 	klgrpset_add(new->lgrp_children, child->lgrp_id);
5730Sstevel@tonic-gate 	klgrpset_copy(new->lgrp_leaves, child->lgrp_leaves);
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 	child->lgrp_parent = new;
5760Sstevel@tonic-gate 	if (old) {
5770Sstevel@tonic-gate 		klgrpset_del(old->lgrp_children, child->lgrp_id);
5780Sstevel@tonic-gate 		klgrpset_add(old->lgrp_children, new->lgrp_id);
5790Sstevel@tonic-gate 		if (changed)
5800Sstevel@tonic-gate 			klgrpset_add(*changed, old->lgrp_id);
5810Sstevel@tonic-gate 		count++;
5820Sstevel@tonic-gate 	}
5830Sstevel@tonic-gate 
5840Sstevel@tonic-gate 	if (changed) {
5850Sstevel@tonic-gate 		klgrpset_add(*changed, child->lgrp_id);
5860Sstevel@tonic-gate 		klgrpset_add(*changed, new->lgrp_id);
5870Sstevel@tonic-gate 	}
5880Sstevel@tonic-gate 	count += 2;
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate #ifdef	DEBUG
5910Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
5920Sstevel@tonic-gate 		prom_printf("lgrp_new_parent: changed %d lgrps: 0x%llx\n",
5930Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
5940Sstevel@tonic-gate #endif	/* DEBUG */
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	return (count);
5970Sstevel@tonic-gate }
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate /*
6010Sstevel@tonic-gate  * Proprogate resources of new leaf into parent lgroup of given child
6020Sstevel@tonic-gate  */
6030Sstevel@tonic-gate int
lgrp_proprogate(lgrp_t * newleaf,lgrp_t * child,int latency,klgrpset_t * changed)6040Sstevel@tonic-gate lgrp_proprogate(lgrp_t *newleaf, lgrp_t *child, int latency,
6050Sstevel@tonic-gate     klgrpset_t *changed)
6060Sstevel@tonic-gate {
6070Sstevel@tonic-gate 	int	count;
6080Sstevel@tonic-gate 	lgrp_t	*parent;
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	count = 0;
6110Sstevel@tonic-gate 	if (changed)
6120Sstevel@tonic-gate 		klgrpset_clear(*changed);
6130Sstevel@tonic-gate 
6140Sstevel@tonic-gate 	if (child == NULL || child->lgrp_parent == NULL)
6150Sstevel@tonic-gate 		return (0);
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 	parent = child->lgrp_parent;
6180Sstevel@tonic-gate 	klgrpset_or(parent->lgrp_leaves, child->lgrp_leaves);
6190Sstevel@tonic-gate 	if (changed)
6200Sstevel@tonic-gate 		klgrpset_add(*changed, parent->lgrp_id);
6210Sstevel@tonic-gate 	count++;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	/*
6240Sstevel@tonic-gate 	 * Don't proprogate new leaf resources to parent if it already
6250Sstevel@tonic-gate 	 * contains these resources
6260Sstevel@tonic-gate 	 */
6270Sstevel@tonic-gate 	if (lgrp_rsets_member_all(parent->lgrp_set, newleaf->lgrp_id)) {
6280Sstevel@tonic-gate #ifdef	DEBUG
6290Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
6300Sstevel@tonic-gate 			prom_printf("lgrp_proprogate: changed %d lgrps:"
6310Sstevel@tonic-gate 			    " 0x%llx\n",
6320Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
6330Sstevel@tonic-gate #endif	/* DEBUG */
6340Sstevel@tonic-gate 		return (count);
6350Sstevel@tonic-gate 	}
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate 	/*
6380Sstevel@tonic-gate 	 * Add leaf resources to parent lgroup
6390Sstevel@tonic-gate 	 */
6400Sstevel@tonic-gate 	lgrp_rsets_add(newleaf->lgrp_set, parent->lgrp_set);
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate #ifdef	DEBUG
6430Sstevel@tonic-gate 	if (lgrp_topo_debug > 1) {
6440Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: newleaf %d(0x%p), "
6450Sstevel@tonic-gate 		    "latency %d, child %d(0x%p), parent %d(0x%p)\n",
6467632SNick.Todd@Sun.COM 		    newleaf->lgrp_id, (void *)newleaf, latency, child->lgrp_id,
6477632SNick.Todd@Sun.COM 		    (void *)child, parent->lgrp_id, (void *)parent);
6480Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: parent's leaves becomes 0x%llx\n",
6490Sstevel@tonic-gate 		    (u_longlong_t)parent->lgrp_leaves);
6500Sstevel@tonic-gate 	}
6510Sstevel@tonic-gate 	if (lgrp_topo_debug > 0) {
6520Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: adding to parent %d (0x%p)\n",
6537632SNick.Todd@Sun.COM 		    parent->lgrp_id, (void *)parent);
6540Sstevel@tonic-gate 		lgrp_rsets_print("parent resources become:", parent->lgrp_set);
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	if (lgrp_topo_debug > 2 && changed)
6580Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: changed %d lgrps: 0x%llx\n",
6590Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate #endif	/* DEBUG */
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	return (count);
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate /*
6680Sstevel@tonic-gate  * Split parent lgroup of given child if child's leaf decendant (oldleaf) has
6690Sstevel@tonic-gate  * different latency to new leaf lgroup (newleaf) than leaf lgroups of given
6700Sstevel@tonic-gate  * child's siblings
6710Sstevel@tonic-gate  */
6720Sstevel@tonic-gate int
lgrp_split(lgrp_t * oldleaf,lgrp_t * newleaf,lgrp_t * child,klgrpset_t * changed)6730Sstevel@tonic-gate lgrp_split(lgrp_t *oldleaf, lgrp_t *newleaf, lgrp_t *child,
6740Sstevel@tonic-gate     klgrpset_t *changed)
6750Sstevel@tonic-gate {
6760Sstevel@tonic-gate 	klgrpset_t	changes;
6770Sstevel@tonic-gate 	int		count;
6780Sstevel@tonic-gate 	int		i;
6790Sstevel@tonic-gate 	int		latency;
6800Sstevel@tonic-gate 	lgrp_t		*parent;
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 	count = 0;
6830Sstevel@tonic-gate 	if (changed)
6840Sstevel@tonic-gate 		klgrpset_clear(*changed);
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 	if (lgrp_split_off || newleaf == NULL || child == NULL)
6870Sstevel@tonic-gate 		return (0);
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	/*
6900Sstevel@tonic-gate 	 * Parent must have more than one child to have a child split from it
6910Sstevel@tonic-gate 	 * and root lgroup contains all resources and never needs to be split
6920Sstevel@tonic-gate 	 */
6930Sstevel@tonic-gate 	parent = child->lgrp_parent;
6940Sstevel@tonic-gate 	if (parent == NULL || parent->lgrp_childcnt < 2 || parent == lgrp_root)
6950Sstevel@tonic-gate 		return (0);
6960Sstevel@tonic-gate 
6970Sstevel@tonic-gate #ifdef	DEBUG
6980Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
6990Sstevel@tonic-gate 		prom_printf("lgrp_split(0x%p[%d],0x%p[%d],0x%p[%d],0x%p)\n",
7007632SNick.Todd@Sun.COM 		    (void *)oldleaf, oldleaf->lgrp_id,
7017632SNick.Todd@Sun.COM 		    (void *)newleaf, newleaf->lgrp_id,
7027632SNick.Todd@Sun.COM 		    (void *)child, child->lgrp_id, (void *)changed);
7030Sstevel@tonic-gate #endif	/* DEBUG */
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 	/*
7060Sstevel@tonic-gate 	 * Get latency between new leaf and old leaf whose lineage it is
7070Sstevel@tonic-gate 	 * being added
7080Sstevel@tonic-gate 	 */
7090Sstevel@tonic-gate 	latency = lgrp_plat_latency(oldleaf->lgrp_plathand,
7100Sstevel@tonic-gate 	    newleaf->lgrp_plathand);
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 	/*
7130Sstevel@tonic-gate 	 * Check whether all sibling leaves of given child lgroup have same
7140Sstevel@tonic-gate 	 * latency to new leaf
7150Sstevel@tonic-gate 	 */
7160Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++) {
7170Sstevel@tonic-gate 		lgrp_t		*grandparent;
7180Sstevel@tonic-gate 		lgrp_t		*lgrp;
7190Sstevel@tonic-gate 		int		sibling_latency;
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 		lgrp = lgrp_table[i];
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 		/*
7240Sstevel@tonic-gate 		 * Skip non-existent lgroups, old leaf, and any lgroups that
7250Sstevel@tonic-gate 		 * don't have parent as common ancestor
7260Sstevel@tonic-gate 		 */
7270Sstevel@tonic-gate 		if (!LGRP_EXISTS(lgrp) || lgrp == oldleaf ||
7280Sstevel@tonic-gate 		    !klgrpset_ismember(parent->lgrp_leaves, lgrp->lgrp_id))
7290Sstevel@tonic-gate 			continue;
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 		/*
7320Sstevel@tonic-gate 		 * Same latency, so skip
7330Sstevel@tonic-gate 		 */
7340Sstevel@tonic-gate 		sibling_latency = lgrp_plat_latency(lgrp->lgrp_plathand,
7350Sstevel@tonic-gate 		    newleaf->lgrp_plathand);
7360Sstevel@tonic-gate #ifdef	DEBUG
7370Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
7380Sstevel@tonic-gate 			prom_printf("lgrp_split: latency(%d,%d) %d,"
7390Sstevel@tonic-gate 			    " latency(%d,%d) %d\n",
7400Sstevel@tonic-gate 			    oldleaf->lgrp_id, newleaf->lgrp_id, latency,
7410Sstevel@tonic-gate 			    lgrp->lgrp_id, newleaf->lgrp_id, sibling_latency);
7420Sstevel@tonic-gate #endif	/* DEBUG */
7430Sstevel@tonic-gate 		if (sibling_latency == latency)
7440Sstevel@tonic-gate 			continue;
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 		/*
7470Sstevel@tonic-gate 		 * Different latencies, so  remove child from its parent and
7480Sstevel@tonic-gate 		 * make new parent for old leaf with same latency and same
7490Sstevel@tonic-gate 		 * resources
7500Sstevel@tonic-gate 		 */
7510Sstevel@tonic-gate 		parent->lgrp_childcnt--;
7520Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_children, child->lgrp_id);
7530Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_leaves, oldleaf->lgrp_id);
7540Sstevel@tonic-gate 		grandparent = parent->lgrp_parent;
7550Sstevel@tonic-gate 		if (grandparent) {
7560Sstevel@tonic-gate 			grandparent->lgrp_childcnt++;
7570Sstevel@tonic-gate 			klgrpset_add(grandparent->lgrp_children,
7580Sstevel@tonic-gate 			    child->lgrp_id);
7590Sstevel@tonic-gate 			count++;
7600Sstevel@tonic-gate 			if (changed)
7610Sstevel@tonic-gate 				klgrpset_add(*changed, grandparent->lgrp_id);
7620Sstevel@tonic-gate 		}
7630Sstevel@tonic-gate 		child->lgrp_parent = grandparent;
7640Sstevel@tonic-gate 
7650Sstevel@tonic-gate 		count += lgrp_new_parent(child, parent->lgrp_latency,
7660Sstevel@tonic-gate 		    parent->lgrp_set, &changes);
7670Sstevel@tonic-gate 		if (changed) {
7680Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate 			klgrpset_add(*changed, parent->lgrp_id);
7710Sstevel@tonic-gate 			klgrpset_add(*changed, child->lgrp_id);
7720Sstevel@tonic-gate 			count += 2;
7730Sstevel@tonic-gate 		}
7740Sstevel@tonic-gate 
7750Sstevel@tonic-gate 		parent = child->lgrp_parent;
7760Sstevel@tonic-gate #ifdef	DEBUG
7770Sstevel@tonic-gate 		if (lgrp_topo_debug > 0) {
7780Sstevel@tonic-gate 			prom_printf("lgrp_split: new parent %d (0x%p) for"
7790Sstevel@tonic-gate 			    " lgrp %d (0x%p)\n",
7807632SNick.Todd@Sun.COM 			    parent->lgrp_id, (void *)parent,
7817632SNick.Todd@Sun.COM 			    child->lgrp_id, (void *)child);
7820Sstevel@tonic-gate 			lgrp_rsets_print("new parent resources:",
7830Sstevel@tonic-gate 			    parent->lgrp_set);
7840Sstevel@tonic-gate 		}
7850Sstevel@tonic-gate 
7860Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
7870Sstevel@tonic-gate 			prom_printf("lgrp_split: changed %d lgrps: 0x%llx\n",
7880Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
7890Sstevel@tonic-gate #endif	/* DEBUG */
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 		return (count);
7920Sstevel@tonic-gate 	}
7930Sstevel@tonic-gate 
7940Sstevel@tonic-gate #ifdef	DEBUG
7950Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
7960Sstevel@tonic-gate 		prom_printf("lgrp_split: no changes\n");
7970Sstevel@tonic-gate #endif	/* DEBUG */
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 	return (count);
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate /*
8040Sstevel@tonic-gate  * Return height of lgroup topology from given lgroup to root
8050Sstevel@tonic-gate  */
8060Sstevel@tonic-gate int
lgrp_topo_height(lgrp_t * lgrp)8070Sstevel@tonic-gate lgrp_topo_height(lgrp_t *lgrp)
8080Sstevel@tonic-gate {
8090Sstevel@tonic-gate 	int	nlevels;
8100Sstevel@tonic-gate 
8110Sstevel@tonic-gate 	if (!LGRP_EXISTS(lgrp))
8120Sstevel@tonic-gate 		return (0);
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	nlevels = 0;
8150Sstevel@tonic-gate 	while (lgrp != NULL) {
8160Sstevel@tonic-gate 		lgrp = lgrp->lgrp_parent;
8170Sstevel@tonic-gate 		nlevels++;
8180Sstevel@tonic-gate 	}
8190Sstevel@tonic-gate 	return (nlevels);
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate /*
8240Sstevel@tonic-gate  * Add resources of new leaf to old leaf's lineage
8250Sstevel@tonic-gate  *
8260Sstevel@tonic-gate  * Assumes the following:
8270Sstevel@tonic-gate  * - Lgroup hierarchy consists of at least a root lgroup and its leaves
8280Sstevel@tonic-gate  *   including old and new ones given below
8290Sstevel@tonic-gate  * - New leaf lgroup has been created and does not need to have its resources
8300Sstevel@tonic-gate  *   added to it
8310Sstevel@tonic-gate  * - Latencies have been set for root and leaf lgroups
8320Sstevel@tonic-gate  */
8330Sstevel@tonic-gate int
lgrp_lineage_add(lgrp_t * newleaf,lgrp_t * oldleaf,klgrpset_t * changed)8340Sstevel@tonic-gate lgrp_lineage_add(lgrp_t *newleaf, lgrp_t *oldleaf, klgrpset_t *changed)
8350Sstevel@tonic-gate {
8360Sstevel@tonic-gate 	klgrpset_t	changes;
8370Sstevel@tonic-gate 	lgrp_t		*child;
8380Sstevel@tonic-gate 	klgrpset_t	collapse;
8390Sstevel@tonic-gate 	int		count;
8400Sstevel@tonic-gate 	int		latency;
8410Sstevel@tonic-gate 	int		nlevels;
8420Sstevel@tonic-gate 	lgrp_t		*parent;
8430Sstevel@tonic-gate 	int		proprogate;
8440Sstevel@tonic-gate 	int		total;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	count = total = 0;
8480Sstevel@tonic-gate 	if (changed)
8490Sstevel@tonic-gate 		klgrpset_clear(*changed);
8500Sstevel@tonic-gate 
8510Sstevel@tonic-gate 	if (newleaf == NULL || oldleaf == NULL || newleaf == oldleaf)
8520Sstevel@tonic-gate 		return (0);
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate #ifdef	DEBUG
8550Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
8560Sstevel@tonic-gate 		prom_printf("\nlgrp_lineage_add(0x%p[%d],0x%p[%d],0x%p)\n",
8577632SNick.Todd@Sun.COM 		    (void *)newleaf, newleaf->lgrp_id,
8587632SNick.Todd@Sun.COM 		    (void *)oldleaf, oldleaf->lgrp_id,
8597632SNick.Todd@Sun.COM 		    (void *)changed);
8600Sstevel@tonic-gate #endif	/* DEBUG */
8610Sstevel@tonic-gate 
8620Sstevel@tonic-gate 	/*
8630Sstevel@tonic-gate 	 * Get latency between old and new leaves, so we can determine
8640Sstevel@tonic-gate 	 * where the new leaf fits in the old leaf's lineage
8650Sstevel@tonic-gate 	 */
8660Sstevel@tonic-gate 	latency = lgrp_plat_latency(oldleaf->lgrp_plathand,
8670Sstevel@tonic-gate 	    newleaf->lgrp_plathand);
8680Sstevel@tonic-gate 
8690Sstevel@tonic-gate 	/*
8700Sstevel@tonic-gate 	 * Determine height of lgroup topology from old leaf to root lgroup,
8710Sstevel@tonic-gate 	 * so height of topology may be limited if necessary
8720Sstevel@tonic-gate 	 */
8730Sstevel@tonic-gate 	nlevels = lgrp_topo_height(oldleaf);
8740Sstevel@tonic-gate 
8750Sstevel@tonic-gate #ifdef	DEBUG
8760Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
8770Sstevel@tonic-gate 		prom_printf("lgrp_lineage_add: latency(%d,%d) 0x%x, ht %d\n",
8780Sstevel@tonic-gate 		    oldleaf->lgrp_id, newleaf->lgrp_id, latency, nlevels);
8790Sstevel@tonic-gate #endif	/* DEBUG */
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate 	/*
8820Sstevel@tonic-gate 	 * Can't add new leaf to old leaf's lineage if we haven't
8830Sstevel@tonic-gate 	 * determined latency between them yet
8840Sstevel@tonic-gate 	 */
8850Sstevel@tonic-gate 	if (latency == 0)
8860Sstevel@tonic-gate 		return (0);
8870Sstevel@tonic-gate 
8880Sstevel@tonic-gate 	child = oldleaf;
8890Sstevel@tonic-gate 	parent = child->lgrp_parent;
8900Sstevel@tonic-gate 	proprogate = 0;
8910Sstevel@tonic-gate 	klgrpset_clear(collapse);
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 	/*
8940Sstevel@tonic-gate 	 * Lineage of old leaf is basically a sorted list of the other leaves
8950Sstevel@tonic-gate 	 * from closest to farthest, so find where to add new leaf to the
8960Sstevel@tonic-gate 	 * lineage and proprogate its resources from that point up to the root
8970Sstevel@tonic-gate 	 * lgroup since parent lgroups contain all the resources of their
8980Sstevel@tonic-gate 	 * children
8990Sstevel@tonic-gate 	 */
9000Sstevel@tonic-gate 	do {
9010Sstevel@tonic-gate 		klgrpset_t	rset[LGRP_RSRC_COUNT];
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate #ifdef	DEBUG
9040Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
9050Sstevel@tonic-gate 			prom_printf("lgrp_lineage_add: child %d (0x%p), parent"
9060Sstevel@tonic-gate 			    " %d (0x%p)\n",
9077632SNick.Todd@Sun.COM 			    child->lgrp_id, (void *)child,
9087632SNick.Todd@Sun.COM 			    parent->lgrp_id, (void *)parent);
9090Sstevel@tonic-gate #endif	/* DEBUG */
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 		/*
9120Sstevel@tonic-gate 		 * See whether parent lgroup needs to be split
9130Sstevel@tonic-gate 		 *
9140Sstevel@tonic-gate 		 * May need to split parent lgroup when it is ancestor to more
9150Sstevel@tonic-gate 		 * than one leaf, but all its leaves don't have latency to new
9160Sstevel@tonic-gate 		 * leaf within the parent lgroup's latency
9170Sstevel@tonic-gate 		 * NOTE: Don't want to collapse this lgroup since we just split
9180Sstevel@tonic-gate 		 * it from parent
9190Sstevel@tonic-gate 		 */
9200Sstevel@tonic-gate 		count = lgrp_split(oldleaf, newleaf, child, &changes);
9210Sstevel@tonic-gate 		if (count) {
9220Sstevel@tonic-gate #ifdef	DEBUG
9230Sstevel@tonic-gate 			if (lgrp_topo_debug > 0)
9240Sstevel@tonic-gate 				prom_printf("lgrp_lineage_add: setting parent"
9250Sstevel@tonic-gate 				    " for child %d from %d to %d\n",
9260Sstevel@tonic-gate 				    child->lgrp_id, parent->lgrp_id,
9270Sstevel@tonic-gate 				    child->lgrp_parent->lgrp_id);
9280Sstevel@tonic-gate #endif	/* DEBUG */
9290Sstevel@tonic-gate 			parent = child->lgrp_parent;
9300Sstevel@tonic-gate 			total += count;
9310Sstevel@tonic-gate 			if (changed)
9320Sstevel@tonic-gate 				klgrpset_or(*changed, changes);
9330Sstevel@tonic-gate 		}
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 		/*
9360Sstevel@tonic-gate 		 * Already found where resources of new leaf belong in old
9370Sstevel@tonic-gate 		 * leaf's lineage, so proprogate resources of new leaf up
9380Sstevel@tonic-gate 		 * through rest of ancestors
9390Sstevel@tonic-gate 		 */
9400Sstevel@tonic-gate 		if (proprogate) {
9410Sstevel@tonic-gate 			total += lgrp_proprogate(newleaf, child, latency,
9420Sstevel@tonic-gate 			    &changes);
9430Sstevel@tonic-gate 			if (changed)
9440Sstevel@tonic-gate 				klgrpset_or(*changed, changes);
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 			parent = child->lgrp_parent;
9470Sstevel@tonic-gate 			klgrpset_add(collapse, parent->lgrp_id);
9480Sstevel@tonic-gate 			child = parent;
9490Sstevel@tonic-gate 			parent = parent->lgrp_parent;
9500Sstevel@tonic-gate 			continue;
9510Sstevel@tonic-gate 		}
9520Sstevel@tonic-gate 
9530Sstevel@tonic-gate #ifdef	DEBUG
9540Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
9550Sstevel@tonic-gate 			prom_printf("lgrp_lineage_add: latency 0x%x,"
9560Sstevel@tonic-gate 			    " parent latency 0x%x\n",
9570Sstevel@tonic-gate 			    latency, parent->lgrp_latency);
9580Sstevel@tonic-gate #endif	/* DEBUG */
9590Sstevel@tonic-gate 		/*
9600Sstevel@tonic-gate 		 * As we work our way from the old leaf to the root lgroup,
9610Sstevel@tonic-gate 		 * new leaf resources should go in between two lgroups or into
9620Sstevel@tonic-gate 		 * one of the parent lgroups somewhere along the line
9630Sstevel@tonic-gate 		 */
9640Sstevel@tonic-gate 		if (latency < parent->lgrp_latency) {
9650Sstevel@tonic-gate 			lgrp_t	*intermed;
9660Sstevel@tonic-gate 
9670Sstevel@tonic-gate 			/*
9680Sstevel@tonic-gate 			 * New leaf resources should go in between current
9690Sstevel@tonic-gate 			 * child and parent
9700Sstevel@tonic-gate 			 */
9710Sstevel@tonic-gate #ifdef	DEBUG
9720Sstevel@tonic-gate 			if (lgrp_topo_debug > 0)
9730Sstevel@tonic-gate 				prom_printf("lgrp_lineage_add: "
9740Sstevel@tonic-gate 				    "latency < parent latency\n");
9750Sstevel@tonic-gate #endif	/* DEBUG */
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 			/*
9780Sstevel@tonic-gate 			 * Create lgroup with desired resources and insert it
9790Sstevel@tonic-gate 			 * between child and parent
9800Sstevel@tonic-gate 			 */
9810Sstevel@tonic-gate 			lgrp_rsets_copy(child->lgrp_set, rset);
9820Sstevel@tonic-gate 			lgrp_rsets_add(newleaf->lgrp_set, rset);
9830Sstevel@tonic-gate 			if (nlevels >= lgrp_topo_levels) {
984*12762SEthindra.Ramamurthy@Sun.COM 
985*12762SEthindra.Ramamurthy@Sun.COM #ifdef	DEBUG
986*12762SEthindra.Ramamurthy@Sun.COM 				if (lgrp_topo_debug > 0) {
987*12762SEthindra.Ramamurthy@Sun.COM 					prom_printf("lgrp_lineage_add: nlevels "
988*12762SEthindra.Ramamurthy@Sun.COM 					    "%d > lgrp_topo_levels %d\n",
989*12762SEthindra.Ramamurthy@Sun.COM 					    nlevels, lgrp_topo_levels);
990*12762SEthindra.Ramamurthy@Sun.COM 					lgrp_rsets_print("rset ", rset);
991*12762SEthindra.Ramamurthy@Sun.COM 				}
992*12762SEthindra.Ramamurthy@Sun.COM #endif	/* DEBUG */
993*12762SEthindra.Ramamurthy@Sun.COM 
994*12762SEthindra.Ramamurthy@Sun.COM 				if (parent == lgrp_root) {
995*12762SEthindra.Ramamurthy@Sun.COM 					/*
996*12762SEthindra.Ramamurthy@Sun.COM 					 * Don't proprogate new leaf resources
997*12762SEthindra.Ramamurthy@Sun.COM 					 * to parent, if it already contains
998*12762SEthindra.Ramamurthy@Sun.COM 					 * these resources
999*12762SEthindra.Ramamurthy@Sun.COM 					 */
1000*12762SEthindra.Ramamurthy@Sun.COM 					if (lgrp_rsets_member_all(
1001*12762SEthindra.Ramamurthy@Sun.COM 					    parent->lgrp_set, newleaf->lgrp_id))
1002*12762SEthindra.Ramamurthy@Sun.COM 						break;
1003*12762SEthindra.Ramamurthy@Sun.COM 
1004*12762SEthindra.Ramamurthy@Sun.COM 					total += lgrp_proprogate(newleaf, child,
1005*12762SEthindra.Ramamurthy@Sun.COM 					    latency, &changes);
10060Sstevel@tonic-gate 					break;
1007*12762SEthindra.Ramamurthy@Sun.COM 				}
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate #ifdef	DEBUG
10100Sstevel@tonic-gate 				if (lgrp_topo_debug > 0) {
10110Sstevel@tonic-gate 					prom_printf("lgrp_lineage_add: "
10120Sstevel@tonic-gate 					    "replaced parent lgrp %d at 0x%p"
10130Sstevel@tonic-gate 					    " for lgrp %d\n",
10147632SNick.Todd@Sun.COM 					    parent->lgrp_id, (void *)parent,
10150Sstevel@tonic-gate 					    child->lgrp_id);
10160Sstevel@tonic-gate 					lgrp_rsets_print("old parent"
10170Sstevel@tonic-gate 					    " resources:", parent->lgrp_set);
10180Sstevel@tonic-gate 					lgrp_rsets_print("new parent "
10190Sstevel@tonic-gate 					    "resources:", rset);
10200Sstevel@tonic-gate 				}
10210Sstevel@tonic-gate #endif	/* DEBUG */
10220Sstevel@tonic-gate 				/*
10230Sstevel@tonic-gate 				 * Replace contents of parent with new
10240Sstevel@tonic-gate 				 * leaf + child resources since new leaf is
10250Sstevel@tonic-gate 				 * closer and shift its parent's resources to
10260Sstevel@tonic-gate 				 * its parent, etc. until root lgroup reached
10270Sstevel@tonic-gate 				 */
10280Sstevel@tonic-gate 				lgrp_rsets_replace(rset, latency, parent, 1);
10290Sstevel@tonic-gate 				if (*changed)
10300Sstevel@tonic-gate 					klgrpset_or(*changed, parent->lgrp_id);
10310Sstevel@tonic-gate 				total++;
10320Sstevel@tonic-gate 				proprogate++;
10330Sstevel@tonic-gate 			} else {
1034*12762SEthindra.Ramamurthy@Sun.COM 
1035*12762SEthindra.Ramamurthy@Sun.COM #ifdef	DEBUG
1036*12762SEthindra.Ramamurthy@Sun.COM 				if (lgrp_topo_debug > 0) {
1037*12762SEthindra.Ramamurthy@Sun.COM 					prom_printf("lgrp_lineage_add: "
1038*12762SEthindra.Ramamurthy@Sun.COM 					    "lgrp_new_parent(0x%p,%d)\n",
1039*12762SEthindra.Ramamurthy@Sun.COM 					    (void *)child, latency);
1040*12762SEthindra.Ramamurthy@Sun.COM 					lgrp_rsets_print("rset ", rset);
1041*12762SEthindra.Ramamurthy@Sun.COM 				}
1042*12762SEthindra.Ramamurthy@Sun.COM #endif	/* DEBUG */
1043*12762SEthindra.Ramamurthy@Sun.COM 
10440Sstevel@tonic-gate 				total += lgrp_new_parent(child, latency, rset,
10450Sstevel@tonic-gate 				    &changes);
10460Sstevel@tonic-gate 				intermed = child->lgrp_parent;
10470Sstevel@tonic-gate 				klgrpset_add(collapse, intermed->lgrp_id);
10480Sstevel@tonic-gate 				if (changed)
10490Sstevel@tonic-gate 					klgrpset_or(*changed, changes);
10500Sstevel@tonic-gate 				child = intermed;
10510Sstevel@tonic-gate 				proprogate++;
10520Sstevel@tonic-gate #ifdef	DEBUG
10530Sstevel@tonic-gate 				if (lgrp_topo_debug > 0) {
10540Sstevel@tonic-gate 					prom_printf("lgrp_lineage_add: new "
10550Sstevel@tonic-gate 					    "parent lgrp %d at 0x%p for "
10560Sstevel@tonic-gate 					    "lgrp %d\n", intermed->lgrp_id,
10577632SNick.Todd@Sun.COM 					    (void *)intermed, child->lgrp_id);
10580Sstevel@tonic-gate 					lgrp_rsets_print("new parent "
10590Sstevel@tonic-gate 					    "resources:", rset);
10600Sstevel@tonic-gate 				}
10610Sstevel@tonic-gate #endif	/* DEBUG */
10620Sstevel@tonic-gate 				continue;
10630Sstevel@tonic-gate 			}
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate 		} else if (latency == parent->lgrp_latency) {
10660Sstevel@tonic-gate 			/*
10670Sstevel@tonic-gate 			 * New leaf resources should go into parent
10680Sstevel@tonic-gate 			 */
10690Sstevel@tonic-gate #ifdef	DEBUG
10700Sstevel@tonic-gate 			if (lgrp_topo_debug > 0)
10710Sstevel@tonic-gate 				prom_printf("lgrp_lineage_add: latency == "
10720Sstevel@tonic-gate 				    "parent latency\n");
10730Sstevel@tonic-gate #endif	/* DEBUG */
10740Sstevel@tonic-gate 
10750Sstevel@tonic-gate 			/*
10760Sstevel@tonic-gate 			 * It's already there, so don't need to do anything.
10770Sstevel@tonic-gate 			 */
10780Sstevel@tonic-gate 			if (lgrp_rsets_member_all(parent->lgrp_set,
10790Sstevel@tonic-gate 			    newleaf->lgrp_id))
10800Sstevel@tonic-gate 				break;
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 			total += lgrp_proprogate(newleaf, child, latency,
10830Sstevel@tonic-gate 			    &changes);
10840Sstevel@tonic-gate 			parent = child->lgrp_parent;
10850Sstevel@tonic-gate 			klgrpset_add(collapse, parent->lgrp_id);
10860Sstevel@tonic-gate 			if (changed)
10870Sstevel@tonic-gate 				klgrpset_or(*changed, changes);
10880Sstevel@tonic-gate 
10890Sstevel@tonic-gate 			proprogate++;
10900Sstevel@tonic-gate 		}
10910Sstevel@tonic-gate 
10920Sstevel@tonic-gate 		child = parent;
10930Sstevel@tonic-gate 		parent = parent->lgrp_parent;
10940Sstevel@tonic-gate 	} while (parent != NULL);
10950Sstevel@tonic-gate 
10960Sstevel@tonic-gate 	/*
10970Sstevel@tonic-gate 	 * Consolidate any duplicate lgroups of ones just changed
10980Sstevel@tonic-gate 	 * Assume that there were no duplicates before last round of changes
10990Sstevel@tonic-gate 	 */
11000Sstevel@tonic-gate #ifdef	DEBUG
11010Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
11020Sstevel@tonic-gate 		prom_printf("lgrp_lineage_add: collapsing dups....\n");
11030Sstevel@tonic-gate #endif	/* DEBUG */
11040Sstevel@tonic-gate 
11050Sstevel@tonic-gate 	total += lgrp_collapse_dups(collapse, lgrp_collapse_equidist,
11060Sstevel@tonic-gate 	    &changes);
11070Sstevel@tonic-gate 	if (changed)
11080Sstevel@tonic-gate 		klgrpset_or(*changed, changes);
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate #ifdef	DEBUG
11110Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
11120Sstevel@tonic-gate 		prom_printf("lgrp_lineage_add: changed %d lgrps: 0x%llx\n",
11130Sstevel@tonic-gate 		    total, (u_longlong_t)*changed);
11140Sstevel@tonic-gate #endif	/* DEBUG */
11150Sstevel@tonic-gate 
11160Sstevel@tonic-gate 	return (total);
11170Sstevel@tonic-gate }
11180Sstevel@tonic-gate 
11190Sstevel@tonic-gate 
11200Sstevel@tonic-gate /*
11210Sstevel@tonic-gate  * Add leaf lgroup to lgroup topology
11220Sstevel@tonic-gate  */
11230Sstevel@tonic-gate int
lgrp_leaf_add(lgrp_t * leaf,lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)11240Sstevel@tonic-gate lgrp_leaf_add(lgrp_t *leaf, lgrp_t **lgrps, int lgrp_count,
11250Sstevel@tonic-gate     klgrpset_t *changed)
11260Sstevel@tonic-gate {
11270Sstevel@tonic-gate 	klgrpset_t	changes;
11280Sstevel@tonic-gate 	int		count;
11290Sstevel@tonic-gate 	int		i;
11300Sstevel@tonic-gate 	int		latency;
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 ||
11330Sstevel@tonic-gate 	    !lgrp_initialized);
11340Sstevel@tonic-gate 
11350Sstevel@tonic-gate #ifdef	DEBUG
11360Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
11370Sstevel@tonic-gate 		prom_printf("\nlgrp_leaf_add(0x%p[%d],0x%p,%d,0x%p)\n",
11387632SNick.Todd@Sun.COM 		    (void *)leaf, leaf->lgrp_id, (void *)lgrps, lgrp_count,
11397632SNick.Todd@Sun.COM 		    (void *)changed);
11400Sstevel@tonic-gate #endif	/* DEBUG */
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	count = 0;
11430Sstevel@tonic-gate 	if (changed)
11440Sstevel@tonic-gate 		klgrpset_clear(*changed);
11450Sstevel@tonic-gate 
11460Sstevel@tonic-gate 	/*
11470Sstevel@tonic-gate 	 * Initialize parent of leaf lgroup to root
11480Sstevel@tonic-gate 	 */
11490Sstevel@tonic-gate 	if (leaf->lgrp_parent == NULL) {
11500Sstevel@tonic-gate 		leaf->lgrp_parent = lgrp_root;
11510Sstevel@tonic-gate 		lgrp_root->lgrp_childcnt++;
11520Sstevel@tonic-gate 		klgrpset_add(lgrp_root->lgrp_children, leaf->lgrp_id);
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 		klgrpset_or(lgrp_root->lgrp_leaves, leaf->lgrp_leaves);
11550Sstevel@tonic-gate 		lgrp_rsets_add(leaf->lgrp_set, lgrp_root->lgrp_set);
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate #ifdef	DEBUG
11580Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
11590Sstevel@tonic-gate 			lgrp_rsets_print("lgrp_leaf_add: root lgrp resources",
11600Sstevel@tonic-gate 			    lgrp_root->lgrp_set);
11610Sstevel@tonic-gate #endif	/* DEBUG */
11620Sstevel@tonic-gate 
11630Sstevel@tonic-gate 		if (changed) {
11640Sstevel@tonic-gate 			klgrpset_add(*changed, lgrp_root->lgrp_id);
11650Sstevel@tonic-gate 			klgrpset_add(*changed, leaf->lgrp_id);
11660Sstevel@tonic-gate 		}
11670Sstevel@tonic-gate 		count += 2;
11680Sstevel@tonic-gate 	}
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 	/*
11710Sstevel@tonic-gate 	 * Can't add leaf lgroup to rest of topology (and vice versa) unless
11720Sstevel@tonic-gate 	 * latency for it is available
11730Sstevel@tonic-gate 	 */
11740Sstevel@tonic-gate 	latency = lgrp_plat_latency(leaf->lgrp_plathand, leaf->lgrp_plathand);
11750Sstevel@tonic-gate 	if (latency == 0) {
11760Sstevel@tonic-gate #ifdef	DEBUG
11770Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
11780Sstevel@tonic-gate 			prom_printf("lgrp_leaf_add: changed %d lgrps: 0x%llx\n",
11790Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
11800Sstevel@tonic-gate #endif	/* DEBUG */
11810Sstevel@tonic-gate 		return (count);
11820Sstevel@tonic-gate 	}
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	/*
11850Sstevel@tonic-gate 	 * Make sure that root and leaf lgroup latencies are set
11860Sstevel@tonic-gate 	 */
11870Sstevel@tonic-gate 	lgrp_root->lgrp_latency = lgrp_plat_latency(lgrp_root->lgrp_plathand,
11880Sstevel@tonic-gate 	    lgrp_root->lgrp_plathand);
11890Sstevel@tonic-gate 	leaf->lgrp_latency = latency;
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	/*
11920Sstevel@tonic-gate 	 * Add leaf to lineage of other leaves and vice versa
11930Sstevel@tonic-gate 	 * since leaves come into existence at different times
11940Sstevel@tonic-gate 	 */
11950Sstevel@tonic-gate 	for (i = 0; i < lgrp_count; i++) {
11960Sstevel@tonic-gate 		lgrp_t		*lgrp;
11970Sstevel@tonic-gate 
11980Sstevel@tonic-gate 		lgrp = lgrps[i];
11990Sstevel@tonic-gate 
12000Sstevel@tonic-gate 		/*
12010Sstevel@tonic-gate 		 * Skip non-existent lgroups, new leaf lgroup, and
12020Sstevel@tonic-gate 		 * non-leaf lgroups
12030Sstevel@tonic-gate 		 */
12040Sstevel@tonic-gate 		if (!LGRP_EXISTS(lgrp) || lgrp == leaf ||
12050Sstevel@tonic-gate 		    lgrp->lgrp_childcnt != 0) {
12060Sstevel@tonic-gate #ifdef	DEBUG
12070Sstevel@tonic-gate 			if (lgrp_topo_debug > 1)
12080Sstevel@tonic-gate 				prom_printf("lgrp_leaf_add: skip "
12090Sstevel@tonic-gate 				    "lgrp %d at 0x%p\n",
12107632SNick.Todd@Sun.COM 				    lgrp->lgrp_id, (void *)lgrp);
12110Sstevel@tonic-gate #endif	/* DEBUG */
12120Sstevel@tonic-gate 			continue;
12130Sstevel@tonic-gate 		}
12140Sstevel@tonic-gate 
12150Sstevel@tonic-gate #ifdef	DEBUG
12160Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
12170Sstevel@tonic-gate 			prom_printf("lgrp_leaf_add: lgrp %d (0x%p) =>"
12180Sstevel@tonic-gate 			    " lgrp %d (0x%p)\n",
12197632SNick.Todd@Sun.COM 			    leaf->lgrp_id, (void *)leaf, lgrp->lgrp_id,
12207632SNick.Todd@Sun.COM 			    (void *)lgrp);
12210Sstevel@tonic-gate #endif	/* DEBUG */
12220Sstevel@tonic-gate 
12230Sstevel@tonic-gate 		count += lgrp_lineage_add(leaf, lgrp, &changes);
12240Sstevel@tonic-gate 		if (changed)
12250Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 		count += lgrp_lineage_add(lgrp, leaf, &changes);
12280Sstevel@tonic-gate 		if (changed)
12290Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
12300Sstevel@tonic-gate 	}
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate #ifdef	DEBUG
12330Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
12340Sstevel@tonic-gate 		prom_printf("lgrp_leaf_add: changed %d lgrps: 0x%llx\n",
12350Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
12360Sstevel@tonic-gate #endif	/* DEBUG */
12370Sstevel@tonic-gate 
12380Sstevel@tonic-gate 	return (count);
12390Sstevel@tonic-gate }
12400Sstevel@tonic-gate 
12410Sstevel@tonic-gate 
12420Sstevel@tonic-gate /*
12430Sstevel@tonic-gate  * Remove resources of leaf from lgroup hierarchy
12440Sstevel@tonic-gate  */
12450Sstevel@tonic-gate int
lgrp_leaf_delete(lgrp_t * leaf,lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)12460Sstevel@tonic-gate lgrp_leaf_delete(lgrp_t *leaf, lgrp_t **lgrps, int lgrp_count,
12470Sstevel@tonic-gate     klgrpset_t *changed)
12480Sstevel@tonic-gate {
12490Sstevel@tonic-gate 	klgrpset_t	changes;
12500Sstevel@tonic-gate 	klgrpset_t	collapse;
12510Sstevel@tonic-gate 	int		count;
12520Sstevel@tonic-gate 	int		i;
12530Sstevel@tonic-gate 	lgrp_t		*lgrp;
12540Sstevel@tonic-gate 
12550Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 ||
12560Sstevel@tonic-gate 	    !lgrp_initialized);
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 	count = 0;
12590Sstevel@tonic-gate 	klgrpset_clear(collapse);
12600Sstevel@tonic-gate 	if (changed)
12610Sstevel@tonic-gate 		klgrpset_clear(*changed);
12620Sstevel@tonic-gate 
12630Sstevel@tonic-gate 	/*
12640Sstevel@tonic-gate 	 * Nothing to do if no leaf given
12650Sstevel@tonic-gate 	 */
12660Sstevel@tonic-gate 	if (leaf == NULL)
12670Sstevel@tonic-gate 		return (0);
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate #ifdef	DEBUG
12700Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
12710Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete(0x%p[%d],0x%p,%d,0x%p)\n",
12727632SNick.Todd@Sun.COM 		    (void *)leaf, leaf->lgrp_id, (void *)lgrps, lgrp_count,
12737632SNick.Todd@Sun.COM 		    (void *)changed);
12740Sstevel@tonic-gate #endif	/* DEBUG */
12750Sstevel@tonic-gate 
12760Sstevel@tonic-gate 	/*
12770Sstevel@tonic-gate 	 * Remove leaf from any lgroups containing its resources
12780Sstevel@tonic-gate 	 */
12790Sstevel@tonic-gate 	for (i = 0; i < lgrp_count; i++) {
12800Sstevel@tonic-gate 		lgrp = lgrps[i];
12810Sstevel@tonic-gate 		if (lgrp == NULL || lgrp->lgrp_id == LGRP_NONE ||
12820Sstevel@tonic-gate 		    !lgrp_rsets_member(lgrp->lgrp_set, leaf->lgrp_id))
12830Sstevel@tonic-gate 			continue;
12840Sstevel@tonic-gate 
12850Sstevel@tonic-gate #ifdef	DEBUG
12860Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
12870Sstevel@tonic-gate 			prom_printf("lgrp_leaf_delete: remove leaf from"
12887632SNick.Todd@Sun.COM 			    " lgrp %d at %p\n", lgrp->lgrp_id, (void *)lgrp);
12890Sstevel@tonic-gate #endif	/* DEBUG */
12900Sstevel@tonic-gate 
12910Sstevel@tonic-gate 		lgrp_rsets_delete(lgrp, leaf->lgrp_id, 0);
12920Sstevel@tonic-gate 		klgrpset_del(lgrp->lgrp_leaves, leaf->lgrp_id);
12930Sstevel@tonic-gate 
12940Sstevel@tonic-gate 		klgrpset_add(collapse, lgrp->lgrp_id);
12950Sstevel@tonic-gate 		count++;
12960Sstevel@tonic-gate 	}
12970Sstevel@tonic-gate 
12980Sstevel@tonic-gate 	/*
12990Sstevel@tonic-gate 	 * Remove leaf and its ancestors that don't have any other children
13000Sstevel@tonic-gate 	 */
13010Sstevel@tonic-gate #ifdef	DEBUG
13020Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
13030Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete: remove leaf and ancestors\n");
13040Sstevel@tonic-gate #endif	/* DEBUG */
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 	count += lgrp_ancestor_delete(leaf, &changes);
13070Sstevel@tonic-gate 	klgrpset_or(collapse, changes);
13080Sstevel@tonic-gate 	klgrpset_add(collapse, leaf->lgrp_id);
13090Sstevel@tonic-gate 	count++;
13100Sstevel@tonic-gate 	lgrp_destroy(leaf);
13110Sstevel@tonic-gate 
13120Sstevel@tonic-gate 	/*
13130Sstevel@tonic-gate 	 * Consolidate any duplicate lgroups of ones just changed
13140Sstevel@tonic-gate 	 * Assume that there were no duplicates before last round of changes
13150Sstevel@tonic-gate 	 */
13160Sstevel@tonic-gate #ifdef	DEBUG
13170Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
13180Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete: collapsing dups\n");
13190Sstevel@tonic-gate #endif	/* DEBUG */
13200Sstevel@tonic-gate 	count += lgrp_collapse_dups(collapse, lgrp_collapse_equidist,
13210Sstevel@tonic-gate 	    &changes);
13220Sstevel@tonic-gate 	klgrpset_or(collapse, changes);
13230Sstevel@tonic-gate 	if (changed)
13240Sstevel@tonic-gate 		klgrpset_copy(*changed, collapse);
13250Sstevel@tonic-gate 
13260Sstevel@tonic-gate #ifdef	DEBUG
13270Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
13280Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete: changed %d lgrps: 0x%llx\n",
13290Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
13300Sstevel@tonic-gate #endif	/* DEBUG */
13310Sstevel@tonic-gate 
13320Sstevel@tonic-gate 	return (count);
13330Sstevel@tonic-gate }
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate 
13360Sstevel@tonic-gate /*
13370Sstevel@tonic-gate  * Flatten lgroup topology down to height specified
13380Sstevel@tonic-gate  */
13390Sstevel@tonic-gate int
lgrp_topo_flatten(int levels,lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)13400Sstevel@tonic-gate lgrp_topo_flatten(int levels, lgrp_t **lgrps, int lgrp_count,
13410Sstevel@tonic-gate     klgrpset_t *changed)
13420Sstevel@tonic-gate {
13430Sstevel@tonic-gate 	int	count;
13440Sstevel@tonic-gate 	int	i;
13450Sstevel@tonic-gate 	lgrp_t	*lgrp;
13465608Srv207048 	lgrp_handle_t hdl;
13470Sstevel@tonic-gate 
13480Sstevel@tonic-gate 	/*
13490Sstevel@tonic-gate 	 * Only flatten down to 2 level for now
13500Sstevel@tonic-gate 	 */
13510Sstevel@tonic-gate 	if (levels != 2)
13520Sstevel@tonic-gate 		return (0);
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 	/*
13550Sstevel@tonic-gate 	 * Look for non-leaf lgroups to remove and leaf lgroups to reparent
13560Sstevel@tonic-gate 	 */
13570Sstevel@tonic-gate 	count = 0;
13580Sstevel@tonic-gate 	for (i = 0; i <= lgrp_count; i++) {
13590Sstevel@tonic-gate 		/*
13600Sstevel@tonic-gate 		 * Skip non-existent lgroups and root
13610Sstevel@tonic-gate 		 */
13620Sstevel@tonic-gate 		lgrp = lgrps[i];
13635602Srv207048 		if (!LGRP_EXISTS(lgrp))
13640Sstevel@tonic-gate 			continue;
13650Sstevel@tonic-gate 
13665608Srv207048 		hdl = lgrp->lgrp_plathand;
13675608Srv207048 
13685608Srv207048 		if (lgrp == lgrp_root) {
13695608Srv207048 			lgrp->lgrp_latency = lgrp_plat_latency(hdl, hdl);
13705602Srv207048 			continue;
13715602Srv207048 		}
13725602Srv207048 
13730Sstevel@tonic-gate 		if (lgrp->lgrp_childcnt > 0) {
13740Sstevel@tonic-gate 			lgrp_t	*parent;
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 			/*
13770Sstevel@tonic-gate 			 * Remove non-leaf lgroup from lgroup topology
13780Sstevel@tonic-gate 			 */
13790Sstevel@tonic-gate 			parent = lgrp->lgrp_parent;
13800Sstevel@tonic-gate 			if (changed) {
13810Sstevel@tonic-gate 				klgrpset_add(*changed, lgrp->lgrp_id);
13820Sstevel@tonic-gate 				klgrpset_add(*changed, parent->lgrp_id);
13830Sstevel@tonic-gate 				count += 2;
13840Sstevel@tonic-gate 			}
13850Sstevel@tonic-gate 			if (parent) {
13860Sstevel@tonic-gate 				klgrpset_del(parent->lgrp_children,
13870Sstevel@tonic-gate 				    lgrp->lgrp_id);
13880Sstevel@tonic-gate 				parent->lgrp_childcnt--;
13890Sstevel@tonic-gate 			}
13900Sstevel@tonic-gate 			lgrp_destroy(lgrp);
13910Sstevel@tonic-gate 		} else if (lgrp->lgrp_parent != lgrp_root) {
13920Sstevel@tonic-gate 			/*
13930Sstevel@tonic-gate 			 * Reparent leaf lgroup to root
13940Sstevel@tonic-gate 			 */
13950Sstevel@tonic-gate 			if (changed) {
13960Sstevel@tonic-gate 				klgrpset_add(*changed, lgrp_root->lgrp_id);
13970Sstevel@tonic-gate 				klgrpset_add(*changed, lgrp->lgrp_id);
13980Sstevel@tonic-gate 				count += 2;
13990Sstevel@tonic-gate 			}
14000Sstevel@tonic-gate 			lgrp->lgrp_parent = lgrp_root;
14010Sstevel@tonic-gate 			klgrpset_add(lgrp_root->lgrp_children, lgrp->lgrp_id);
14020Sstevel@tonic-gate 			lgrp_root->lgrp_childcnt++;
14030Sstevel@tonic-gate 			klgrpset_add(lgrp_root->lgrp_leaves, lgrp->lgrp_id);
14045602Srv207048 
14055608Srv207048 			lgrp->lgrp_latency = lgrp_plat_latency(hdl, hdl);
14060Sstevel@tonic-gate 		}
14070Sstevel@tonic-gate 	}
14080Sstevel@tonic-gate 
14090Sstevel@tonic-gate 	return (count);
14100Sstevel@tonic-gate }
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 
14130Sstevel@tonic-gate /*
14140Sstevel@tonic-gate  * Return current height limit for lgroup topology
14150Sstevel@tonic-gate  */
14160Sstevel@tonic-gate int
lgrp_topo_ht_limit(void)14170Sstevel@tonic-gate lgrp_topo_ht_limit(void)
14180Sstevel@tonic-gate {
14190Sstevel@tonic-gate 	return (lgrp_topo_levels);
14200Sstevel@tonic-gate }
14210Sstevel@tonic-gate 
14220Sstevel@tonic-gate 
14230Sstevel@tonic-gate /*
14240Sstevel@tonic-gate  * Return default height limit for lgroup topology
14250Sstevel@tonic-gate  */
14260Sstevel@tonic-gate int
lgrp_topo_ht_limit_default(void)14270Sstevel@tonic-gate lgrp_topo_ht_limit_default(void)
14280Sstevel@tonic-gate {
14290Sstevel@tonic-gate 	return (LGRP_TOPO_LEVELS);
14300Sstevel@tonic-gate }
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate 
14330Sstevel@tonic-gate /*
14340Sstevel@tonic-gate  * Set height limit for lgroup topology
14350Sstevel@tonic-gate  */
14360Sstevel@tonic-gate int
lgrp_topo_ht_limit_set(int ht)14370Sstevel@tonic-gate lgrp_topo_ht_limit_set(int ht)
14380Sstevel@tonic-gate {
14390Sstevel@tonic-gate 	if (ht > LGRP_TOPO_LEVELS_MAX)
14400Sstevel@tonic-gate 		lgrp_topo_levels = LGRP_TOPO_LEVELS_MAX;
14410Sstevel@tonic-gate 	else
14420Sstevel@tonic-gate 		lgrp_topo_levels = ht;
14430Sstevel@tonic-gate 
14440Sstevel@tonic-gate 	return (ht);
14450Sstevel@tonic-gate }
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate /*
14490Sstevel@tonic-gate  * Update lgroup topology for any leaves that don't have their latency set
14500Sstevel@tonic-gate  *
14510Sstevel@tonic-gate  * This may happen on some machines when the lgroup platform support doesn't
14520Sstevel@tonic-gate  * know the latencies between nodes soon enough to provide it when the
14530Sstevel@tonic-gate  * resources are being added.  If the lgroup platform code needs to probe
14540Sstevel@tonic-gate  * memory to determine the latencies between nodes, it must wait until the
14550Sstevel@tonic-gate  * CPUs become active so at least one CPU in each node can probe memory in
14560Sstevel@tonic-gate  * each node.
14570Sstevel@tonic-gate  */
14580Sstevel@tonic-gate int
lgrp_topo_update(lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)14590Sstevel@tonic-gate lgrp_topo_update(lgrp_t **lgrps, int lgrp_count, klgrpset_t *changed)
14600Sstevel@tonic-gate {
14610Sstevel@tonic-gate 	klgrpset_t	changes;
14620Sstevel@tonic-gate 	int		count;
14630Sstevel@tonic-gate 	int		i;
14640Sstevel@tonic-gate 	lgrp_t		*lgrp;
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate 	count = 0;
14670Sstevel@tonic-gate 	if (changed)
14680Sstevel@tonic-gate 		klgrpset_clear(*changed);
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate 	/*
14710Sstevel@tonic-gate 	 * For UMA machines, make sure that root lgroup contains all
14720Sstevel@tonic-gate 	 * resources.  The root lgrp should also name itself as its own leaf
14730Sstevel@tonic-gate 	 */
14740Sstevel@tonic-gate 	if (nlgrps == 1) {
14750Sstevel@tonic-gate 		for (i = 0; i < LGRP_RSRC_COUNT; i++)
14760Sstevel@tonic-gate 			klgrpset_add(lgrp_root->lgrp_set[i],
14770Sstevel@tonic-gate 			    lgrp_root->lgrp_id);
14780Sstevel@tonic-gate 		klgrpset_add(lgrp_root->lgrp_leaves, lgrp_root->lgrp_id);
14790Sstevel@tonic-gate 		return (0);
14800Sstevel@tonic-gate 	}
14810Sstevel@tonic-gate 
14820Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
14830Sstevel@tonic-gate 	pause_cpus(NULL);
14840Sstevel@tonic-gate 
14850Sstevel@tonic-gate 	/*
14860Sstevel@tonic-gate 	 * Look for any leaf lgroup without its latency set, finish adding it
14870Sstevel@tonic-gate 	 * to the lgroup topology assuming that it exists and has the root
14880Sstevel@tonic-gate 	 * lgroup as its parent, and update the memory nodes of all lgroups
14890Sstevel@tonic-gate 	 * that have it as a memory resource.
14900Sstevel@tonic-gate 	 */
14910Sstevel@tonic-gate 	for (i = 0; i < lgrp_count; i++) {
14920Sstevel@tonic-gate 		lgrp = lgrps[i];
14930Sstevel@tonic-gate 
14940Sstevel@tonic-gate 		/*
14950Sstevel@tonic-gate 		 * Skip non-existent and non-leaf lgroups and any lgroup
14960Sstevel@tonic-gate 		 * with its latency set already
14970Sstevel@tonic-gate 		 */
14980Sstevel@tonic-gate 		if (lgrp == NULL || lgrp->lgrp_id == LGRP_NONE ||
14990Sstevel@tonic-gate 		    lgrp->lgrp_childcnt != 0 || lgrp->lgrp_latency != 0)
15000Sstevel@tonic-gate 			continue;
15010Sstevel@tonic-gate 
15020Sstevel@tonic-gate #ifdef	DEBUG
15030Sstevel@tonic-gate 		if (lgrp_topo_debug > 1) {
15040Sstevel@tonic-gate 			prom_printf("\nlgrp_topo_update: updating lineage "
15057632SNick.Todd@Sun.COM 			    "of lgrp %d at 0x%p\n", lgrp->lgrp_id,
15067632SNick.Todd@Sun.COM 			    (void *)lgrp);
15070Sstevel@tonic-gate 		}
15080Sstevel@tonic-gate #endif	/* DEBUG */
15090Sstevel@tonic-gate 
15100Sstevel@tonic-gate 		count += lgrp_leaf_add(lgrp, lgrps, lgrp_count, &changes);
15110Sstevel@tonic-gate 		if (changed)
15120Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 		if (!klgrpset_isempty(changes))
15150Sstevel@tonic-gate 			(void) lgrp_mnode_update(changes, NULL);
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate #ifdef	DEBUG
15180Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
15190Sstevel@tonic-gate 			prom_printf("lgrp_topo_update: changed %d lgrps: "
15200Sstevel@tonic-gate 			    "0x%llx\n",
15210Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
15220Sstevel@tonic-gate #endif	/* DEBUG */
15230Sstevel@tonic-gate 	}
15240Sstevel@tonic-gate 
15250Sstevel@tonic-gate 	if (lgrp_topo_levels < LGRP_TOPO_LEVELS && lgrp_topo_levels == 2) {
15260Sstevel@tonic-gate 		count += lgrp_topo_flatten(2, lgrps, lgrp_count, changed);
15270Sstevel@tonic-gate 		(void) lpl_topo_flatten(2);
15280Sstevel@tonic-gate 	}
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 	start_cpus();
15310Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
15320Sstevel@tonic-gate 
15330Sstevel@tonic-gate 	return (count);
15340Sstevel@tonic-gate }
15350Sstevel@tonic-gate 
15360Sstevel@tonic-gate #ifdef	DEBUG
15370Sstevel@tonic-gate void
lgrp_print(lgrp_t * lgrp)15380Sstevel@tonic-gate lgrp_print(lgrp_t *lgrp)
15390Sstevel@tonic-gate {
15400Sstevel@tonic-gate 	lgrp_t	*parent;
15410Sstevel@tonic-gate 
15420Sstevel@tonic-gate 	prom_printf("LGRP %d", lgrp->lgrp_id);
15430Sstevel@tonic-gate 	if (lgrp->lgrp_childcnt == 0)
15440Sstevel@tonic-gate 		prom_printf(" (plathand %p)\n",
15450Sstevel@tonic-gate 		    (void *)lgrp->lgrp_plathand);
15460Sstevel@tonic-gate 	else
15470Sstevel@tonic-gate 		prom_printf("\n");
15480Sstevel@tonic-gate 
15490Sstevel@tonic-gate 	prom_printf("\tlatency %d\n", lgrp->lgrp_latency);
15500Sstevel@tonic-gate 
15510Sstevel@tonic-gate 	lgrp_rsets_print("\tresources", lgrp->lgrp_set);
15520Sstevel@tonic-gate 
15530Sstevel@tonic-gate 	parent = lgrp->lgrp_parent;
15547632SNick.Todd@Sun.COM 	prom_printf("\tparent 0x%p", (void *)parent);
15550Sstevel@tonic-gate 	if (parent)
15560Sstevel@tonic-gate 		prom_printf("[%d]\n", parent->lgrp_id);
15570Sstevel@tonic-gate 	else
15580Sstevel@tonic-gate 		prom_printf("\n");
15590Sstevel@tonic-gate 
15600Sstevel@tonic-gate 	prom_printf("\tchild count %d, children ", lgrp->lgrp_childcnt);
15610Sstevel@tonic-gate 	klgrpset_print(lgrp->lgrp_children);
15620Sstevel@tonic-gate 
15630Sstevel@tonic-gate 	prom_printf("\tleaves ");
15640Sstevel@tonic-gate 	klgrpset_print(lgrp->lgrp_leaves);
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate 
15670Sstevel@tonic-gate 
15680Sstevel@tonic-gate void
lgrp_topo_print(lgrp_t ** lgrps,int lgrp_max)15690Sstevel@tonic-gate lgrp_topo_print(lgrp_t **lgrps, int lgrp_max)
15700Sstevel@tonic-gate {
15710Sstevel@tonic-gate 	klgrpset_t	siblings;
15720Sstevel@tonic-gate 
15730Sstevel@tonic-gate 	lgrp_print(lgrp_root);
15740Sstevel@tonic-gate 	siblings = lgrp_root->lgrp_children;
15750Sstevel@tonic-gate 	while (!klgrpset_isempty(siblings)) {
15760Sstevel@tonic-gate 		klgrpset_t	children;
15770Sstevel@tonic-gate 		int		i;
15780Sstevel@tonic-gate 
15790Sstevel@tonic-gate 		klgrpset_clear(children);
15800Sstevel@tonic-gate 		for (i = 0; i <= lgrp_max; i++) {
15810Sstevel@tonic-gate 			lgrp_t	*lgrp;
15820Sstevel@tonic-gate 
15830Sstevel@tonic-gate 			lgrp = lgrps[i];
15840Sstevel@tonic-gate 			if (lgrp == NULL || !klgrpset_ismember(siblings, i))
15850Sstevel@tonic-gate 				continue;
15860Sstevel@tonic-gate 			lgrp_print(lgrp);
15870Sstevel@tonic-gate 			klgrpset_or(children, lgrp->lgrp_children);
15880Sstevel@tonic-gate 		}
15890Sstevel@tonic-gate 		klgrpset_copy(siblings, children);
15900Sstevel@tonic-gate 	}
15910Sstevel@tonic-gate }
15920Sstevel@tonic-gate #endif	/* DEBUG */
1593