xref: /illumos-gate/usr/src/uts/common/os/lgrp_topo.c (revision 0ed5c46e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5950a2babSrv  * Common Development and Distribution License (the "License").
6950a2babSrv  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
222bf5f692SEthindra Ramamurthy  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate  * lgroup topology
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/cpupart.h>
307c478bd9Sstevel@tonic-gate #include <sys/lgrp.h>
317c478bd9Sstevel@tonic-gate #include <sys/promif.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #define	LGRP_TOPO_LEVELS	4	/* default height limit */
367c478bd9Sstevel@tonic-gate #define	LGRP_TOPO_LEVELS_MAX	4	/* max height limit */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * Only collapse lgroups which have same latency (and resources)
417c478bd9Sstevel@tonic-gate  */
427c478bd9Sstevel@tonic-gate int		lgrp_collapse_equidist = 1;
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate int		lgrp_collapse_off = 1;	/* disable collapsing of duplicates */
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * Height to limit lgroup topology
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate unsigned int	lgrp_topo_levels = LGRP_TOPO_LEVELS;
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate int		lgrp_split_off = 1;	/* disable splitting lgroups */
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #ifdef	DEBUG
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate  * Debugging output
567c478bd9Sstevel@tonic-gate  * - 0: off
577c478bd9Sstevel@tonic-gate  * - >0: on and bigger means more
587c478bd9Sstevel@tonic-gate  */
597c478bd9Sstevel@tonic-gate int	lgrp_topo_debug = 0;
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate void
klgrpset_print(klgrpset_t lgrpset)637c478bd9Sstevel@tonic-gate klgrpset_print(klgrpset_t lgrpset)
647c478bd9Sstevel@tonic-gate {
657c478bd9Sstevel@tonic-gate 	int	i;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	prom_printf("0x%llx(", (u_longlong_t)lgrpset);
697c478bd9Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++)
707c478bd9Sstevel@tonic-gate 		if (klgrpset_ismember(lgrpset, i))
717c478bd9Sstevel@tonic-gate 			prom_printf("%d ", i);
727c478bd9Sstevel@tonic-gate 	prom_printf(")\n");
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate void
lgrp_rsets_print(char * string,klgrpset_t * rsets)777c478bd9Sstevel@tonic-gate lgrp_rsets_print(char *string, klgrpset_t *rsets)
787c478bd9Sstevel@tonic-gate {
797c478bd9Sstevel@tonic-gate 	int	i;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	prom_printf("%s\n", string);
827c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
837c478bd9Sstevel@tonic-gate 		klgrpset_print(rsets[i]);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Add "from" lgroup resources to "to" lgroup resources
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate void
lgrp_rsets_add(klgrpset_t * from,klgrpset_t * to)927c478bd9Sstevel@tonic-gate lgrp_rsets_add(klgrpset_t *from, klgrpset_t *to)
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate 	int	i;
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
977c478bd9Sstevel@tonic-gate 		klgrpset_or(to[i], from[i]);
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * Copy "from" lgroup resources to "to" lgroup resources
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@tonic-gate void
lgrp_rsets_copy(klgrpset_t * from,klgrpset_t * to)1057c478bd9Sstevel@tonic-gate lgrp_rsets_copy(klgrpset_t *from, klgrpset_t *to)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 	int	i;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1107c478bd9Sstevel@tonic-gate 		to[i] = from[i];
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate  * Delete given lgroup ID from lgroup resource set of specified lgroup
1167c478bd9Sstevel@tonic-gate  * and its ancestors if "follow_parent" is set
1177c478bd9Sstevel@tonic-gate  */
1187c478bd9Sstevel@tonic-gate void
lgrp_rsets_delete(lgrp_t * lgrp,lgrp_id_t lgrpid,int follow_parent)1197c478bd9Sstevel@tonic-gate lgrp_rsets_delete(lgrp_t *lgrp, lgrp_id_t lgrpid, int follow_parent)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate 	int	i;
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	while (lgrp != NULL) {
1247c478bd9Sstevel@tonic-gate 		for (i = 0; i < LGRP_RSRC_COUNT; i++)
1257c478bd9Sstevel@tonic-gate 			klgrpset_del(lgrp->lgrp_set[i], lgrpid);
1267c478bd9Sstevel@tonic-gate 		if (!follow_parent)
1277c478bd9Sstevel@tonic-gate 			break;
1287c478bd9Sstevel@tonic-gate 		lgrp = lgrp->lgrp_parent;
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate /*
1347c478bd9Sstevel@tonic-gate  * Return whether given lgroup resource set empty
1357c478bd9Sstevel@tonic-gate  */
1367c478bd9Sstevel@tonic-gate int
lgrp_rsets_empty(klgrpset_t * rset)1377c478bd9Sstevel@tonic-gate lgrp_rsets_empty(klgrpset_t *rset)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	int	i;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1427c478bd9Sstevel@tonic-gate 		if (!klgrpset_isempty(rset[i]))
1437c478bd9Sstevel@tonic-gate 			return (0);
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	return (1);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * Return whether given lgroup resource sets are same
1517c478bd9Sstevel@tonic-gate  */
1527c478bd9Sstevel@tonic-gate int
lgrp_rsets_equal(klgrpset_t * rset1,klgrpset_t * rset2)1537c478bd9Sstevel@tonic-gate lgrp_rsets_equal(klgrpset_t *rset1, klgrpset_t *rset2)
1547c478bd9Sstevel@tonic-gate {
1557c478bd9Sstevel@tonic-gate 	int	i;
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1587c478bd9Sstevel@tonic-gate 		if (rset1[i] != rset2[i])
1597c478bd9Sstevel@tonic-gate 			return (0);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 	return (1);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate /*
1667c478bd9Sstevel@tonic-gate  * Return whether specified lgroup ID is in given lgroup resource set
1677c478bd9Sstevel@tonic-gate  */
1687c478bd9Sstevel@tonic-gate int
lgrp_rsets_member(klgrpset_t * rset,lgrp_id_t lgrpid)1697c478bd9Sstevel@tonic-gate lgrp_rsets_member(klgrpset_t *rset, lgrp_id_t lgrpid)
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate 	int	i;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1747c478bd9Sstevel@tonic-gate 		if (klgrpset_ismember(rset[i], lgrpid))
1757c478bd9Sstevel@tonic-gate 			return (1);
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate 	return (0);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate  * Return whether specified lgroup ID is in all lgroup resources
1837c478bd9Sstevel@tonic-gate  */
1847c478bd9Sstevel@tonic-gate int
lgrp_rsets_member_all(klgrpset_t * rset,lgrp_id_t lgrpid)1857c478bd9Sstevel@tonic-gate lgrp_rsets_member_all(klgrpset_t *rset, lgrp_id_t lgrpid)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	int	i;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++)
1907c478bd9Sstevel@tonic-gate 		if (!klgrpset_ismember(rset[i], lgrpid))
1917c478bd9Sstevel@tonic-gate 			return (0);
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	return (1);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * Replace resources for given lgroup with specified resources at given
1997c478bd9Sstevel@tonic-gate  * latency and shift its old resources to its parent and its parent's resources
2007c478bd9Sstevel@tonic-gate  * to its parent, etc. until root lgroup reached
2017c478bd9Sstevel@tonic-gate  */
2027c478bd9Sstevel@tonic-gate void
lgrp_rsets_replace(klgrpset_t * rset,int latency,lgrp_t * lgrp,int shift)2037c478bd9Sstevel@tonic-gate lgrp_rsets_replace(klgrpset_t *rset, int latency, lgrp_t *lgrp, int shift)
2047c478bd9Sstevel@tonic-gate {
2057c478bd9Sstevel@tonic-gate 	lgrp_t		*cur;
2067c478bd9Sstevel@tonic-gate 	int		lat_new;
2077c478bd9Sstevel@tonic-gate 	int		lat_saved;
2087c478bd9Sstevel@tonic-gate 	klgrpset_t	rset_new[LGRP_RSRC_COUNT];
2097c478bd9Sstevel@tonic-gate 	klgrpset_t	rset_saved[LGRP_RSRC_COUNT];
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	cur = lgrp;
2127c478bd9Sstevel@tonic-gate 	lat_saved = latency;
2137c478bd9Sstevel@tonic-gate 	lgrp_rsets_copy(rset, rset_saved);
2147c478bd9Sstevel@tonic-gate 	while (cur && cur != lgrp_root) {
2157c478bd9Sstevel@tonic-gate 		/*
2167c478bd9Sstevel@tonic-gate 		 * Save current resources and latency to insert in parent and
2177c478bd9Sstevel@tonic-gate 		 * then replace with new resources and latency
2187c478bd9Sstevel@tonic-gate 		 */
2197c478bd9Sstevel@tonic-gate 		lgrp_rsets_copy(rset_saved, rset_new);
2207c478bd9Sstevel@tonic-gate 		lgrp_rsets_copy(cur->lgrp_set, rset_saved);
2217c478bd9Sstevel@tonic-gate 		lgrp_rsets_copy(rset_new, cur->lgrp_set);
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 		lat_new = lat_saved;
2247c478bd9Sstevel@tonic-gate 		lat_saved = cur->lgrp_latency;
2257c478bd9Sstevel@tonic-gate 		cur->lgrp_latency = lat_new;
2267c478bd9Sstevel@tonic-gate 		if (!shift)
2277c478bd9Sstevel@tonic-gate 			break;
2287c478bd9Sstevel@tonic-gate 		cur = cur->lgrp_parent;
2297c478bd9Sstevel@tonic-gate 	}
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate /*
2347c478bd9Sstevel@tonic-gate  * Set "to" lgroup resource set with given lgroup ID
2357c478bd9Sstevel@tonic-gate  */
2367c478bd9Sstevel@tonic-gate void
lgrp_rsets_set(klgrpset_t * to,lgrp_id_t lgrpid)2377c478bd9Sstevel@tonic-gate lgrp_rsets_set(klgrpset_t *to, lgrp_id_t lgrpid)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	klgrpset_t	from;
2407c478bd9Sstevel@tonic-gate 	int		i;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	klgrpset_clear(from);
2437c478bd9Sstevel@tonic-gate 	klgrpset_add(from, lgrpid);
2447c478bd9Sstevel@tonic-gate 	for (i = 0; i < LGRP_RSRC_COUNT; i++) {
2457c478bd9Sstevel@tonic-gate 		klgrpset_clear(to[i]);
2467c478bd9Sstevel@tonic-gate 		klgrpset_or(to[i], from);
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate /*
2527c478bd9Sstevel@tonic-gate  * Delete any ancestors of given child lgroup which don't have any other
2537c478bd9Sstevel@tonic-gate  * children
2547c478bd9Sstevel@tonic-gate  */
2557c478bd9Sstevel@tonic-gate int
lgrp_ancestor_delete(lgrp_t * child,klgrpset_t * changed)2567c478bd9Sstevel@tonic-gate lgrp_ancestor_delete(lgrp_t *child, klgrpset_t *changed)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate 	int		count;
2597c478bd9Sstevel@tonic-gate 	lgrp_t		*current;
2607c478bd9Sstevel@tonic-gate 	lgrp_id_t	lgrpid;
2617c478bd9Sstevel@tonic-gate 	lgrp_t		*parent;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2647c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1) {
2657c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_ancestor_delete(0x%p[%d],0x%p)\n",
2668793b36bSNick Todd 		    (void *)child, child->lgrp_id, (void *)changed);
2677c478bd9Sstevel@tonic-gate 	}
2687c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 	count = 0;
2717c478bd9Sstevel@tonic-gate 	if (changed)
2727c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	/*
2757c478bd9Sstevel@tonic-gate 	 * Visit ancestors, decrement child count for each, and remove any
2767c478bd9Sstevel@tonic-gate 	 * that don't have any children left until we reach an ancestor that
2777c478bd9Sstevel@tonic-gate 	 * has multiple children
2787c478bd9Sstevel@tonic-gate 	 */
2797c478bd9Sstevel@tonic-gate 	current = child;
2807c478bd9Sstevel@tonic-gate 	parent = child->lgrp_parent;
2817c478bd9Sstevel@tonic-gate 	lgrpid = current->lgrp_id;
2827c478bd9Sstevel@tonic-gate 	while (parent != NULL) {
2837c478bd9Sstevel@tonic-gate #ifdef	DEBUG
2847c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
2857c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_ancestor_delete: parent %d,"
2867c478bd9Sstevel@tonic-gate 			    " current %d\n",
2877c478bd9Sstevel@tonic-gate 			    parent->lgrp_id, lgrpid);
2887c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_leaves, lgrpid);
2917c478bd9Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_children, lgrpid);
2927c478bd9Sstevel@tonic-gate 		parent->lgrp_childcnt--;
2937c478bd9Sstevel@tonic-gate 		if (changed)
2947c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, parent->lgrp_id);
2957c478bd9Sstevel@tonic-gate 		count++;
2967c478bd9Sstevel@tonic-gate 		if (parent->lgrp_childcnt != 0)
2977c478bd9Sstevel@tonic-gate 			break;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 		current = parent;
3007c478bd9Sstevel@tonic-gate 		parent = current->lgrp_parent;
3017c478bd9Sstevel@tonic-gate 		lgrpid = current->lgrp_id;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3047c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
3057c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_ancestor_delete: destroy"
3067c478bd9Sstevel@tonic-gate 			    " lgrp %d at 0x%p\n",
3078793b36bSNick Todd 			    current->lgrp_id, (void *)current);
3087c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3097c478bd9Sstevel@tonic-gate 		lgrp_destroy(current);
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3137c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
3147c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_ancestor_delete: changed %d lgrps: 0x%llx\n",
3157c478bd9Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
3167c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	return (count);
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate /*
3237c478bd9Sstevel@tonic-gate  * Consolidate lgrp1 into lgrp2
3247c478bd9Sstevel@tonic-gate  */
3257c478bd9Sstevel@tonic-gate int
lgrp_consolidate(lgrp_t * lgrp1,lgrp_t * lgrp2,klgrpset_t * changed)3267c478bd9Sstevel@tonic-gate lgrp_consolidate(lgrp_t *lgrp1, lgrp_t *lgrp2, klgrpset_t *changed)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate 	klgrpset_t	changes;
3297c478bd9Sstevel@tonic-gate 	lgrp_t		*child;
3307c478bd9Sstevel@tonic-gate 	int		count;
3317c478bd9Sstevel@tonic-gate 	int		i;
3327c478bd9Sstevel@tonic-gate 	lgrp_t		*parent;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	/*
3357c478bd9Sstevel@tonic-gate 	 * Leaf lgroups should never need to be consolidated
3367c478bd9Sstevel@tonic-gate 	 */
3377c478bd9Sstevel@tonic-gate 	if (lgrp1 == NULL || lgrp2 == NULL || lgrp1->lgrp_childcnt < 1 ||
3387c478bd9Sstevel@tonic-gate 	    lgrp2->lgrp_childcnt < 1)
3397c478bd9Sstevel@tonic-gate 		return (0);
3407c478bd9Sstevel@tonic-gate 
3417c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3427c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
3437c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_consolidate(0x%p[%d],0x%p[%d],0x%p)\n",
3448793b36bSNick Todd 		    (void *)lgrp1, lgrp1->lgrp_id, (void *)lgrp2,
3458793b36bSNick Todd 		    lgrp2->lgrp_id, (void *)changed);
3467c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	count = 0;
3497c478bd9Sstevel@tonic-gate 	if (changed)
3507c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/*
3537c478bd9Sstevel@tonic-gate 	 * Lgroup represents resources within certain latency, so need to keep
3547c478bd9Sstevel@tonic-gate 	 * biggest latency value of lgroups being consolidated
3557c478bd9Sstevel@tonic-gate 	 */
3567c478bd9Sstevel@tonic-gate 	if (lgrp1->lgrp_latency > lgrp2->lgrp_latency)
3577c478bd9Sstevel@tonic-gate 		lgrp2->lgrp_latency = lgrp1->lgrp_latency;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	/*
3607c478bd9Sstevel@tonic-gate 	 * Delete ancestors of lgrp1 that don't have any other children
3617c478bd9Sstevel@tonic-gate 	 */
3627c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3637c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
3647c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_consolidate: delete ancestors\n");
3657c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3667c478bd9Sstevel@tonic-gate 	count += lgrp_ancestor_delete(lgrp1, &changes);
3677c478bd9Sstevel@tonic-gate 	if (changed) {
3687c478bd9Sstevel@tonic-gate 		klgrpset_or(*changed, changes);
3697c478bd9Sstevel@tonic-gate 		klgrpset_or(*changed, lgrp1->lgrp_id);
3707c478bd9Sstevel@tonic-gate 		count++;
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	/*
3747c478bd9Sstevel@tonic-gate 	 * Reparent children lgroups of lgrp1 to lgrp2
3757c478bd9Sstevel@tonic-gate 	 */
3767c478bd9Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++) {
3777c478bd9Sstevel@tonic-gate 		if (i == lgrp2->lgrp_id ||
3787c478bd9Sstevel@tonic-gate 		    !klgrpset_ismember(lgrp1->lgrp_children, i))
3797c478bd9Sstevel@tonic-gate 			continue;
3807c478bd9Sstevel@tonic-gate 		child = lgrp_table[i];
3817c478bd9Sstevel@tonic-gate 		if (!LGRP_EXISTS(child))
3827c478bd9Sstevel@tonic-gate 			continue;
3837c478bd9Sstevel@tonic-gate #ifdef	DEBUG
3847c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
3857c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_consolidate: reparent "
3867c478bd9Sstevel@tonic-gate 			    "lgrp %d to lgrp %d\n",
3877c478bd9Sstevel@tonic-gate 			    child->lgrp_id, lgrp2->lgrp_id);
3887c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
3897c478bd9Sstevel@tonic-gate 		klgrpset_or(lgrp2->lgrp_leaves, child->lgrp_leaves);
3907c478bd9Sstevel@tonic-gate 		klgrpset_add(lgrp2->lgrp_children, child->lgrp_id);
3917c478bd9Sstevel@tonic-gate 		lgrp2->lgrp_childcnt++;
3927c478bd9Sstevel@tonic-gate 		child->lgrp_parent = lgrp2;
3937c478bd9Sstevel@tonic-gate 		if (changed) {
3947c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, child->lgrp_id);
3957c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, lgrp2->lgrp_id);
3967c478bd9Sstevel@tonic-gate 		}
3977c478bd9Sstevel@tonic-gate 		count += 2;
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	/*
4017c478bd9Sstevel@tonic-gate 	 * Proprogate leaves from lgrp2 to root
4027c478bd9Sstevel@tonic-gate 	 */
4037c478bd9Sstevel@tonic-gate 	child = lgrp2;
4047c478bd9Sstevel@tonic-gate 	parent = child->lgrp_parent;
4057c478bd9Sstevel@tonic-gate 	while (parent != NULL) {
4067c478bd9Sstevel@tonic-gate 		klgrpset_or(parent->lgrp_leaves, child->lgrp_leaves);
4077c478bd9Sstevel@tonic-gate 		if (changed)
4087c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, parent->lgrp_id);
4097c478bd9Sstevel@tonic-gate 		count++;
4107c478bd9Sstevel@tonic-gate 		child = parent;
4117c478bd9Sstevel@tonic-gate 		parent = parent->lgrp_parent;
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4157c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
4167c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_consolidate: destroy lgrp %d at 0x%p\n",
4178793b36bSNick Todd 		    lgrp1->lgrp_id, (void *)lgrp1);
4187c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
4197c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_consolidate: changed %d lgrps: 0x%llx\n",
4207c478bd9Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
4217c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	lgrp_destroy(lgrp1);
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	return (count);
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate 
4287c478bd9Sstevel@tonic-gate /*
4297c478bd9Sstevel@tonic-gate  * Collapse duplicates of target lgroups given
4307c478bd9Sstevel@tonic-gate  */
4317c478bd9Sstevel@tonic-gate int
lgrp_collapse_dups(klgrpset_t target_set,int equidist_only,klgrpset_t * changed)4327c478bd9Sstevel@tonic-gate lgrp_collapse_dups(klgrpset_t target_set, int equidist_only,
4337c478bd9Sstevel@tonic-gate     klgrpset_t *changed)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate 	klgrpset_t	changes;
4367c478bd9Sstevel@tonic-gate 	int		count;
4377c478bd9Sstevel@tonic-gate 	int		i;
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	count = 0;
4407c478bd9Sstevel@tonic-gate 	if (changed)
4417c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
4427c478bd9Sstevel@tonic-gate 
4437c478bd9Sstevel@tonic-gate 	if (lgrp_collapse_off)
4447c478bd9Sstevel@tonic-gate 		return (0);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4477c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
4487c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_collapse_dups(0x%llx)\n",
4497c478bd9Sstevel@tonic-gate 		    (u_longlong_t)target_set);
4507c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	/*
4537c478bd9Sstevel@tonic-gate 	 * Look for duplicates of each target lgroup
4547c478bd9Sstevel@tonic-gate 	 */
4557c478bd9Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++) {
4567c478bd9Sstevel@tonic-gate 		int	j;
4577c478bd9Sstevel@tonic-gate 		lgrp_t	*keep;
4587c478bd9Sstevel@tonic-gate 		lgrp_t	*target;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		target = lgrp_table[i];
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		/*
4637c478bd9Sstevel@tonic-gate 		 * Skip to next lgroup if there isn't one here, this is root
4647c478bd9Sstevel@tonic-gate 		 * or leaf lgroup, or this isn't a target lgroup
4657c478bd9Sstevel@tonic-gate 		 */
4667c478bd9Sstevel@tonic-gate 		if (!LGRP_EXISTS(target) ||
4677c478bd9Sstevel@tonic-gate 		    target == lgrp_root || target->lgrp_childcnt == 0 ||
4687c478bd9Sstevel@tonic-gate 		    !klgrpset_ismember(target_set, target->lgrp_id))
4697c478bd9Sstevel@tonic-gate 			continue;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 		/*
4727c478bd9Sstevel@tonic-gate 		 * Find all lgroups with same resources and latency
4737c478bd9Sstevel@tonic-gate 		 */
4747c478bd9Sstevel@tonic-gate #ifdef	DEBUG
4757c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
4767c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_collapse_dups: find "
4777c478bd9Sstevel@tonic-gate 			    "dups of lgrp %d at 0x%p\n",
4788793b36bSNick Todd 			    target->lgrp_id, (void *)target);
4797c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
4807c478bd9Sstevel@tonic-gate 		keep = NULL;
4817c478bd9Sstevel@tonic-gate 		for (j = 0; j <= lgrp_alloc_max; j++) {
4827c478bd9Sstevel@tonic-gate 			lgrp_t	*lgrp;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 			lgrp = lgrp_table[j];
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 			/*
4877c478bd9Sstevel@tonic-gate 			 * Skip lgroup if there isn't one here, this is root
4887c478bd9Sstevel@tonic-gate 			 * lgroup or leaf (which shouldn't have dups), or this
4897c478bd9Sstevel@tonic-gate 			 * lgroup doesn't have same resources
4907c478bd9Sstevel@tonic-gate 			 */
4917c478bd9Sstevel@tonic-gate 			if (!LGRP_EXISTS(lgrp) ||
4927c478bd9Sstevel@tonic-gate 			    lgrp->lgrp_childcnt == 0 ||
4937c478bd9Sstevel@tonic-gate 			    !lgrp_rsets_equal(lgrp->lgrp_set,
4947c478bd9Sstevel@tonic-gate 			    target->lgrp_set) ||
4957c478bd9Sstevel@tonic-gate 			    (lgrp->lgrp_latency != target->lgrp_latency &&
4967c478bd9Sstevel@tonic-gate 			    equidist_only))
4977c478bd9Sstevel@tonic-gate 				continue;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 			/*
5007c478bd9Sstevel@tonic-gate 			 * Keep first matching lgroup (but always keep root)
5017c478bd9Sstevel@tonic-gate 			 * and consolidate other duplicates into it
5027c478bd9Sstevel@tonic-gate 			 */
5037c478bd9Sstevel@tonic-gate 			if (keep == NULL) {
5047c478bd9Sstevel@tonic-gate 				keep = lgrp;
5057c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5067c478bd9Sstevel@tonic-gate 				if (lgrp_topo_debug > 1)
5077c478bd9Sstevel@tonic-gate 					prom_printf("lgrp_collapse_dups: "
5087c478bd9Sstevel@tonic-gate 					    "keep lgrp %d at 0x%p\n",
5098793b36bSNick Todd 					    keep->lgrp_id, (void *)keep);
5107c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
5117c478bd9Sstevel@tonic-gate 			} else {
5127c478bd9Sstevel@tonic-gate 				if (lgrp == lgrp_root) {
5137c478bd9Sstevel@tonic-gate 					lgrp = keep;
5147c478bd9Sstevel@tonic-gate 					keep = lgrp_root;
5157c478bd9Sstevel@tonic-gate 				}
5167c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5177c478bd9Sstevel@tonic-gate 				if (lgrp_topo_debug > 0)
5187c478bd9Sstevel@tonic-gate 					prom_printf("lgrp_collapse_dups:"
5197c478bd9Sstevel@tonic-gate 					    " consolidate lgrp %d at 0x%p"
5207c478bd9Sstevel@tonic-gate 					    " into lgrp %d at 0x%p\n",
5218793b36bSNick Todd 					    lgrp->lgrp_id, (void *)lgrp,
5228793b36bSNick Todd 					    keep->lgrp_id, (void *)keep);
5237c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
5247c478bd9Sstevel@tonic-gate 				count += lgrp_consolidate(lgrp, keep,
5257c478bd9Sstevel@tonic-gate 				    &changes);
5267c478bd9Sstevel@tonic-gate 				if (changed)
5277c478bd9Sstevel@tonic-gate 					klgrpset_or(*changed, changes);
5287c478bd9Sstevel@tonic-gate 			}
5297c478bd9Sstevel@tonic-gate 		}
5307c478bd9Sstevel@tonic-gate 	}
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5337c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
5347c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_collapse_dups: changed %d lgrps: 0x%llx\n",
5357c478bd9Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
5367c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	return (count);
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate /*
5437c478bd9Sstevel@tonic-gate  * Create new parent lgroup with given latency and resources for
5447c478bd9Sstevel@tonic-gate  * specified child lgroup, and insert it into hierarchy
5457c478bd9Sstevel@tonic-gate  */
5467c478bd9Sstevel@tonic-gate int
lgrp_new_parent(lgrp_t * child,int latency,klgrpset_t * rset,klgrpset_t * changed)5477c478bd9Sstevel@tonic-gate lgrp_new_parent(lgrp_t *child, int latency, klgrpset_t *rset,
5487c478bd9Sstevel@tonic-gate     klgrpset_t *changed)
5497c478bd9Sstevel@tonic-gate {
5507c478bd9Sstevel@tonic-gate 	int	count;
5517c478bd9Sstevel@tonic-gate 	lgrp_t	*new;
5527c478bd9Sstevel@tonic-gate 	lgrp_t	*old;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	count = 0;
5557c478bd9Sstevel@tonic-gate 	if (changed)
5567c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 	/*
5597c478bd9Sstevel@tonic-gate 	 * Create lgroup and set its latency and resources
5607c478bd9Sstevel@tonic-gate 	 */
5617c478bd9Sstevel@tonic-gate 	new = lgrp_create();
5627c478bd9Sstevel@tonic-gate 	new->lgrp_latency = latency;
5637c478bd9Sstevel@tonic-gate 	lgrp_rsets_add(rset, new->lgrp_set);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	/*
5667c478bd9Sstevel@tonic-gate 	 * Insert new lgroup into hierarchy
5677c478bd9Sstevel@tonic-gate 	 */
5687c478bd9Sstevel@tonic-gate 	old = child->lgrp_parent;
5697c478bd9Sstevel@tonic-gate 	new->lgrp_parent = old;
5707c478bd9Sstevel@tonic-gate 	klgrpset_add(new->lgrp_children, child->lgrp_id);
5717c478bd9Sstevel@tonic-gate 	new->lgrp_childcnt++;
5727c478bd9Sstevel@tonic-gate 	klgrpset_add(new->lgrp_children, child->lgrp_id);
5737c478bd9Sstevel@tonic-gate 	klgrpset_copy(new->lgrp_leaves, child->lgrp_leaves);
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	child->lgrp_parent = new;
5767c478bd9Sstevel@tonic-gate 	if (old) {
5777c478bd9Sstevel@tonic-gate 		klgrpset_del(old->lgrp_children, child->lgrp_id);
5787c478bd9Sstevel@tonic-gate 		klgrpset_add(old->lgrp_children, new->lgrp_id);
5797c478bd9Sstevel@tonic-gate 		if (changed)
5807c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, old->lgrp_id);
5817c478bd9Sstevel@tonic-gate 		count++;
5827c478bd9Sstevel@tonic-gate 	}
5837c478bd9Sstevel@tonic-gate 
5847c478bd9Sstevel@tonic-gate 	if (changed) {
5857c478bd9Sstevel@tonic-gate 		klgrpset_add(*changed, child->lgrp_id);
5867c478bd9Sstevel@tonic-gate 		klgrpset_add(*changed, new->lgrp_id);
5877c478bd9Sstevel@tonic-gate 	}
5887c478bd9Sstevel@tonic-gate 	count += 2;
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate #ifdef	DEBUG
5917c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
5927c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_new_parent: changed %d lgrps: 0x%llx\n",
5937c478bd9Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
5947c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	return (count);
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate 
5997c478bd9Sstevel@tonic-gate 
6007c478bd9Sstevel@tonic-gate /*
6017c478bd9Sstevel@tonic-gate  * Proprogate resources of new leaf into parent lgroup of given child
6027c478bd9Sstevel@tonic-gate  */
6037c478bd9Sstevel@tonic-gate int
lgrp_proprogate(lgrp_t * newleaf,lgrp_t * child,int latency,klgrpset_t * changed)6047c478bd9Sstevel@tonic-gate lgrp_proprogate(lgrp_t *newleaf, lgrp_t *child, int latency,
6057c478bd9Sstevel@tonic-gate     klgrpset_t *changed)
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate 	int	count;
6087c478bd9Sstevel@tonic-gate 	lgrp_t	*parent;
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	count = 0;
6117c478bd9Sstevel@tonic-gate 	if (changed)
6127c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	if (child == NULL || child->lgrp_parent == NULL)
6157c478bd9Sstevel@tonic-gate 		return (0);
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	parent = child->lgrp_parent;
6187c478bd9Sstevel@tonic-gate 	klgrpset_or(parent->lgrp_leaves, child->lgrp_leaves);
6197c478bd9Sstevel@tonic-gate 	if (changed)
6207c478bd9Sstevel@tonic-gate 		klgrpset_add(*changed, parent->lgrp_id);
6217c478bd9Sstevel@tonic-gate 	count++;
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	/*
6247c478bd9Sstevel@tonic-gate 	 * Don't proprogate new leaf resources to parent if it already
6257c478bd9Sstevel@tonic-gate 	 * contains these resources
6267c478bd9Sstevel@tonic-gate 	 */
6277c478bd9Sstevel@tonic-gate 	if (lgrp_rsets_member_all(parent->lgrp_set, newleaf->lgrp_id)) {
6287c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6297c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
6307c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_proprogate: changed %d lgrps:"
6317c478bd9Sstevel@tonic-gate 			    " 0x%llx\n",
6327c478bd9Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
6337c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
6347c478bd9Sstevel@tonic-gate 		return (count);
6357c478bd9Sstevel@tonic-gate 	}
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	/*
6387c478bd9Sstevel@tonic-gate 	 * Add leaf resources to parent lgroup
6397c478bd9Sstevel@tonic-gate 	 */
6407c478bd9Sstevel@tonic-gate 	lgrp_rsets_add(newleaf->lgrp_set, parent->lgrp_set);
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6437c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1) {
6447c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: newleaf %d(0x%p), "
6457c478bd9Sstevel@tonic-gate 		    "latency %d, child %d(0x%p), parent %d(0x%p)\n",
6468793b36bSNick Todd 		    newleaf->lgrp_id, (void *)newleaf, latency, child->lgrp_id,
6478793b36bSNick Todd 		    (void *)child, parent->lgrp_id, (void *)parent);
6487c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: parent's leaves becomes 0x%llx\n",
6497c478bd9Sstevel@tonic-gate 		    (u_longlong_t)parent->lgrp_leaves);
6507c478bd9Sstevel@tonic-gate 	}
6517c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 0) {
6527c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: adding to parent %d (0x%p)\n",
6538793b36bSNick Todd 		    parent->lgrp_id, (void *)parent);
6547c478bd9Sstevel@tonic-gate 		lgrp_rsets_print("parent resources become:", parent->lgrp_set);
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 2 && changed)
6587c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_proprogate: changed %d lgrps: 0x%llx\n",
6597c478bd9Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	return (count);
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate /*
6687c478bd9Sstevel@tonic-gate  * Split parent lgroup of given child if child's leaf decendant (oldleaf) has
6697c478bd9Sstevel@tonic-gate  * different latency to new leaf lgroup (newleaf) than leaf lgroups of given
6707c478bd9Sstevel@tonic-gate  * child's siblings
6717c478bd9Sstevel@tonic-gate  */
6727c478bd9Sstevel@tonic-gate int
lgrp_split(lgrp_t * oldleaf,lgrp_t * newleaf,lgrp_t * child,klgrpset_t * changed)6737c478bd9Sstevel@tonic-gate lgrp_split(lgrp_t *oldleaf, lgrp_t *newleaf, lgrp_t *child,
6747c478bd9Sstevel@tonic-gate     klgrpset_t *changed)
6757c478bd9Sstevel@tonic-gate {
6767c478bd9Sstevel@tonic-gate 	klgrpset_t	changes;
6777c478bd9Sstevel@tonic-gate 	int		count;
6787c478bd9Sstevel@tonic-gate 	int		i;
6797c478bd9Sstevel@tonic-gate 	int		latency;
6807c478bd9Sstevel@tonic-gate 	lgrp_t		*parent;
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	count = 0;
6837c478bd9Sstevel@tonic-gate 	if (changed)
6847c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	if (lgrp_split_off || newleaf == NULL || child == NULL)
6877c478bd9Sstevel@tonic-gate 		return (0);
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	/*
6907c478bd9Sstevel@tonic-gate 	 * Parent must have more than one child to have a child split from it
6917c478bd9Sstevel@tonic-gate 	 * and root lgroup contains all resources and never needs to be split
6927c478bd9Sstevel@tonic-gate 	 */
6937c478bd9Sstevel@tonic-gate 	parent = child->lgrp_parent;
6947c478bd9Sstevel@tonic-gate 	if (parent == NULL || parent->lgrp_childcnt < 2 || parent == lgrp_root)
6957c478bd9Sstevel@tonic-gate 		return (0);
6967c478bd9Sstevel@tonic-gate 
6977c478bd9Sstevel@tonic-gate #ifdef	DEBUG
6987c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
6997c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_split(0x%p[%d],0x%p[%d],0x%p[%d],0x%p)\n",
7008793b36bSNick Todd 		    (void *)oldleaf, oldleaf->lgrp_id,
7018793b36bSNick Todd 		    (void *)newleaf, newleaf->lgrp_id,
7028793b36bSNick Todd 		    (void *)child, child->lgrp_id, (void *)changed);
7037c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
7047c478bd9Sstevel@tonic-gate 
7057c478bd9Sstevel@tonic-gate 	/*
7067c478bd9Sstevel@tonic-gate 	 * Get latency between new leaf and old leaf whose lineage it is
7077c478bd9Sstevel@tonic-gate 	 * being added
7087c478bd9Sstevel@tonic-gate 	 */
7097c478bd9Sstevel@tonic-gate 	latency = lgrp_plat_latency(oldleaf->lgrp_plathand,
7107c478bd9Sstevel@tonic-gate 	    newleaf->lgrp_plathand);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	/*
7137c478bd9Sstevel@tonic-gate 	 * Check whether all sibling leaves of given child lgroup have same
7147c478bd9Sstevel@tonic-gate 	 * latency to new leaf
7157c478bd9Sstevel@tonic-gate 	 */
7167c478bd9Sstevel@tonic-gate 	for (i = 0; i <= lgrp_alloc_max; i++) {
7177c478bd9Sstevel@tonic-gate 		lgrp_t		*grandparent;
7187c478bd9Sstevel@tonic-gate 		lgrp_t		*lgrp;
7197c478bd9Sstevel@tonic-gate 		int		sibling_latency;
7207c478bd9Sstevel@tonic-gate 
7217c478bd9Sstevel@tonic-gate 		lgrp = lgrp_table[i];
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 		/*
7247c478bd9Sstevel@tonic-gate 		 * Skip non-existent lgroups, old leaf, and any lgroups that
7257c478bd9Sstevel@tonic-gate 		 * don't have parent as common ancestor
7267c478bd9Sstevel@tonic-gate 		 */
7277c478bd9Sstevel@tonic-gate 		if (!LGRP_EXISTS(lgrp) || lgrp == oldleaf ||
7287c478bd9Sstevel@tonic-gate 		    !klgrpset_ismember(parent->lgrp_leaves, lgrp->lgrp_id))
7297c478bd9Sstevel@tonic-gate 			continue;
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 		/*
7327c478bd9Sstevel@tonic-gate 		 * Same latency, so skip
7337c478bd9Sstevel@tonic-gate 		 */
7347c478bd9Sstevel@tonic-gate 		sibling_latency = lgrp_plat_latency(lgrp->lgrp_plathand,
7357c478bd9Sstevel@tonic-gate 		    newleaf->lgrp_plathand);
7367c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7377c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
7387c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_split: latency(%d,%d) %d,"
7397c478bd9Sstevel@tonic-gate 			    " latency(%d,%d) %d\n",
7407c478bd9Sstevel@tonic-gate 			    oldleaf->lgrp_id, newleaf->lgrp_id, latency,
7417c478bd9Sstevel@tonic-gate 			    lgrp->lgrp_id, newleaf->lgrp_id, sibling_latency);
7427c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
7437c478bd9Sstevel@tonic-gate 		if (sibling_latency == latency)
7447c478bd9Sstevel@tonic-gate 			continue;
7457c478bd9Sstevel@tonic-gate 
7467c478bd9Sstevel@tonic-gate 		/*
7477c478bd9Sstevel@tonic-gate 		 * Different latencies, so  remove child from its parent and
7487c478bd9Sstevel@tonic-gate 		 * make new parent for old leaf with same latency and same
7497c478bd9Sstevel@tonic-gate 		 * resources
7507c478bd9Sstevel@tonic-gate 		 */
7517c478bd9Sstevel@tonic-gate 		parent->lgrp_childcnt--;
7527c478bd9Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_children, child->lgrp_id);
7537c478bd9Sstevel@tonic-gate 		klgrpset_del(parent->lgrp_leaves, oldleaf->lgrp_id);
7547c478bd9Sstevel@tonic-gate 		grandparent = parent->lgrp_parent;
7557c478bd9Sstevel@tonic-gate 		if (grandparent) {
7567c478bd9Sstevel@tonic-gate 			grandparent->lgrp_childcnt++;
7577c478bd9Sstevel@tonic-gate 			klgrpset_add(grandparent->lgrp_children,
7587c478bd9Sstevel@tonic-gate 			    child->lgrp_id);
7597c478bd9Sstevel@tonic-gate 			count++;
7607c478bd9Sstevel@tonic-gate 			if (changed)
7617c478bd9Sstevel@tonic-gate 				klgrpset_add(*changed, grandparent->lgrp_id);
7627c478bd9Sstevel@tonic-gate 		}
7637c478bd9Sstevel@tonic-gate 		child->lgrp_parent = grandparent;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 		count += lgrp_new_parent(child, parent->lgrp_latency,
7667c478bd9Sstevel@tonic-gate 		    parent->lgrp_set, &changes);
7677c478bd9Sstevel@tonic-gate 		if (changed) {
7687c478bd9Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, parent->lgrp_id);
7717c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, child->lgrp_id);
7727c478bd9Sstevel@tonic-gate 			count += 2;
7737c478bd9Sstevel@tonic-gate 		}
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 		parent = child->lgrp_parent;
7767c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7777c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 0) {
7787c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_split: new parent %d (0x%p) for"
7797c478bd9Sstevel@tonic-gate 			    " lgrp %d (0x%p)\n",
7808793b36bSNick Todd 			    parent->lgrp_id, (void *)parent,
7818793b36bSNick Todd 			    child->lgrp_id, (void *)child);
7827c478bd9Sstevel@tonic-gate 			lgrp_rsets_print("new parent resources:",
7837c478bd9Sstevel@tonic-gate 			    parent->lgrp_set);
7847c478bd9Sstevel@tonic-gate 		}
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
7877c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_split: changed %d lgrps: 0x%llx\n",
7887c478bd9Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
7897c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate 		return (count);
7927c478bd9Sstevel@tonic-gate 	}
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate #ifdef	DEBUG
7957c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
7967c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_split: no changes\n");
7977c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	return (count);
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate /*
8047c478bd9Sstevel@tonic-gate  * Return height of lgroup topology from given lgroup to root
8057c478bd9Sstevel@tonic-gate  */
8067c478bd9Sstevel@tonic-gate int
lgrp_topo_height(lgrp_t * lgrp)8077c478bd9Sstevel@tonic-gate lgrp_topo_height(lgrp_t *lgrp)
8087c478bd9Sstevel@tonic-gate {
8097c478bd9Sstevel@tonic-gate 	int	nlevels;
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 	if (!LGRP_EXISTS(lgrp))
8127c478bd9Sstevel@tonic-gate 		return (0);
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	nlevels = 0;
8157c478bd9Sstevel@tonic-gate 	while (lgrp != NULL) {
8167c478bd9Sstevel@tonic-gate 		lgrp = lgrp->lgrp_parent;
8177c478bd9Sstevel@tonic-gate 		nlevels++;
8187c478bd9Sstevel@tonic-gate 	}
8197c478bd9Sstevel@tonic-gate 	return (nlevels);
8207c478bd9Sstevel@tonic-gate }
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate /*
8247c478bd9Sstevel@tonic-gate  * Add resources of new leaf to old leaf's lineage
8257c478bd9Sstevel@tonic-gate  *
8267c478bd9Sstevel@tonic-gate  * Assumes the following:
8277c478bd9Sstevel@tonic-gate  * - Lgroup hierarchy consists of at least a root lgroup and its leaves
8287c478bd9Sstevel@tonic-gate  *   including old and new ones given below
8297c478bd9Sstevel@tonic-gate  * - New leaf lgroup has been created and does not need to have its resources
8307c478bd9Sstevel@tonic-gate  *   added to it
8317c478bd9Sstevel@tonic-gate  * - Latencies have been set for root and leaf lgroups
8327c478bd9Sstevel@tonic-gate  */
8337c478bd9Sstevel@tonic-gate int
lgrp_lineage_add(lgrp_t * newleaf,lgrp_t * oldleaf,klgrpset_t * changed)8347c478bd9Sstevel@tonic-gate lgrp_lineage_add(lgrp_t *newleaf, lgrp_t *oldleaf, klgrpset_t *changed)
8357c478bd9Sstevel@tonic-gate {
8367c478bd9Sstevel@tonic-gate 	klgrpset_t	changes;
8377c478bd9Sstevel@tonic-gate 	lgrp_t		*child;
8387c478bd9Sstevel@tonic-gate 	klgrpset_t	collapse;
8397c478bd9Sstevel@tonic-gate 	int		count;
8407c478bd9Sstevel@tonic-gate 	int		latency;
8417c478bd9Sstevel@tonic-gate 	int		nlevels;
8427c478bd9Sstevel@tonic-gate 	lgrp_t		*parent;
8437c478bd9Sstevel@tonic-gate 	int		proprogate;
8447c478bd9Sstevel@tonic-gate 	int		total;
8457c478bd9Sstevel@tonic-gate 
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	count = total = 0;
8487c478bd9Sstevel@tonic-gate 	if (changed)
8497c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate 	if (newleaf == NULL || oldleaf == NULL || newleaf == oldleaf)
8527c478bd9Sstevel@tonic-gate 		return (0);
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate #ifdef	DEBUG
8557c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
8567c478bd9Sstevel@tonic-gate 		prom_printf("\nlgrp_lineage_add(0x%p[%d],0x%p[%d],0x%p)\n",
8578793b36bSNick Todd 		    (void *)newleaf, newleaf->lgrp_id,
8588793b36bSNick Todd 		    (void *)oldleaf, oldleaf->lgrp_id,
8598793b36bSNick Todd 		    (void *)changed);
8607c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	/*
8637c478bd9Sstevel@tonic-gate 	 * Get latency between old and new leaves, so we can determine
8647c478bd9Sstevel@tonic-gate 	 * where the new leaf fits in the old leaf's lineage
8657c478bd9Sstevel@tonic-gate 	 */
8667c478bd9Sstevel@tonic-gate 	latency = lgrp_plat_latency(oldleaf->lgrp_plathand,
8677c478bd9Sstevel@tonic-gate 	    newleaf->lgrp_plathand);
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	/*
8707c478bd9Sstevel@tonic-gate 	 * Determine height of lgroup topology from old leaf to root lgroup,
8717c478bd9Sstevel@tonic-gate 	 * so height of topology may be limited if necessary
8727c478bd9Sstevel@tonic-gate 	 */
8737c478bd9Sstevel@tonic-gate 	nlevels = lgrp_topo_height(oldleaf);
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate #ifdef	DEBUG
8767c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
8777c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_lineage_add: latency(%d,%d) 0x%x, ht %d\n",
8787c478bd9Sstevel@tonic-gate 		    oldleaf->lgrp_id, newleaf->lgrp_id, latency, nlevels);
8797c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	/*
8827c478bd9Sstevel@tonic-gate 	 * Can't add new leaf to old leaf's lineage if we haven't
8837c478bd9Sstevel@tonic-gate 	 * determined latency between them yet
8847c478bd9Sstevel@tonic-gate 	 */
8857c478bd9Sstevel@tonic-gate 	if (latency == 0)
8867c478bd9Sstevel@tonic-gate 		return (0);
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 	child = oldleaf;
8897c478bd9Sstevel@tonic-gate 	parent = child->lgrp_parent;
8907c478bd9Sstevel@tonic-gate 	proprogate = 0;
8917c478bd9Sstevel@tonic-gate 	klgrpset_clear(collapse);
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	/*
8947c478bd9Sstevel@tonic-gate 	 * Lineage of old leaf is basically a sorted list of the other leaves
8957c478bd9Sstevel@tonic-gate 	 * from closest to farthest, so find where to add new leaf to the
8967c478bd9Sstevel@tonic-gate 	 * lineage and proprogate its resources from that point up to the root
8977c478bd9Sstevel@tonic-gate 	 * lgroup since parent lgroups contain all the resources of their
8987c478bd9Sstevel@tonic-gate 	 * children
8997c478bd9Sstevel@tonic-gate 	 */
9007c478bd9Sstevel@tonic-gate 	do {
9017c478bd9Sstevel@tonic-gate 		klgrpset_t	rset[LGRP_RSRC_COUNT];
9027c478bd9Sstevel@tonic-gate 
9037c478bd9Sstevel@tonic-gate #ifdef	DEBUG
9047c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
9057c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_lineage_add: child %d (0x%p), parent"
9067c478bd9Sstevel@tonic-gate 			    " %d (0x%p)\n",
9078793b36bSNick Todd 			    child->lgrp_id, (void *)child,
9088793b36bSNick Todd 			    parent->lgrp_id, (void *)parent);
9097c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 		/*
9127c478bd9Sstevel@tonic-gate 		 * See whether parent lgroup needs to be split
9137c478bd9Sstevel@tonic-gate 		 *
9147c478bd9Sstevel@tonic-gate 		 * May need to split parent lgroup when it is ancestor to more
9157c478bd9Sstevel@tonic-gate 		 * than one leaf, but all its leaves don't have latency to new
9167c478bd9Sstevel@tonic-gate 		 * leaf within the parent lgroup's latency
9177c478bd9Sstevel@tonic-gate 		 * NOTE: Don't want to collapse this lgroup since we just split
9187c478bd9Sstevel@tonic-gate 		 * it from parent
9197c478bd9Sstevel@tonic-gate 		 */
9207c478bd9Sstevel@tonic-gate 		count = lgrp_split(oldleaf, newleaf, child, &changes);
9217c478bd9Sstevel@tonic-gate 		if (count) {
9227c478bd9Sstevel@tonic-gate #ifdef	DEBUG
9237c478bd9Sstevel@tonic-gate 			if (lgrp_topo_debug > 0)
9247c478bd9Sstevel@tonic-gate 				prom_printf("lgrp_lineage_add: setting parent"
9257c478bd9Sstevel@tonic-gate 				    " for child %d from %d to %d\n",
9267c478bd9Sstevel@tonic-gate 				    child->lgrp_id, parent->lgrp_id,
9277c478bd9Sstevel@tonic-gate 				    child->lgrp_parent->lgrp_id);
9287c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9297c478bd9Sstevel@tonic-gate 			parent = child->lgrp_parent;
9307c478bd9Sstevel@tonic-gate 			total += count;
9317c478bd9Sstevel@tonic-gate 			if (changed)
9327c478bd9Sstevel@tonic-gate 				klgrpset_or(*changed, changes);
9337c478bd9Sstevel@tonic-gate 		}
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 		/*
9367c478bd9Sstevel@tonic-gate 		 * Already found where resources of new leaf belong in old
9377c478bd9Sstevel@tonic-gate 		 * leaf's lineage, so proprogate resources of new leaf up
9387c478bd9Sstevel@tonic-gate 		 * through rest of ancestors
9397c478bd9Sstevel@tonic-gate 		 */
9407c478bd9Sstevel@tonic-gate 		if (proprogate) {
9417c478bd9Sstevel@tonic-gate 			total += lgrp_proprogate(newleaf, child, latency,
9427c478bd9Sstevel@tonic-gate 			    &changes);
9437c478bd9Sstevel@tonic-gate 			if (changed)
9447c478bd9Sstevel@tonic-gate 				klgrpset_or(*changed, changes);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 			parent = child->lgrp_parent;
9477c478bd9Sstevel@tonic-gate 			klgrpset_add(collapse, parent->lgrp_id);
9487c478bd9Sstevel@tonic-gate 			child = parent;
9497c478bd9Sstevel@tonic-gate 			parent = parent->lgrp_parent;
9507c478bd9Sstevel@tonic-gate 			continue;
9517c478bd9Sstevel@tonic-gate 		}
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate #ifdef	DEBUG
9547c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
9557c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_lineage_add: latency 0x%x,"
9567c478bd9Sstevel@tonic-gate 			    " parent latency 0x%x\n",
9577c478bd9Sstevel@tonic-gate 			    latency, parent->lgrp_latency);
9587c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9597c478bd9Sstevel@tonic-gate 		/*
9607c478bd9Sstevel@tonic-gate 		 * As we work our way from the old leaf to the root lgroup,
9617c478bd9Sstevel@tonic-gate 		 * new leaf resources should go in between two lgroups or into
9627c478bd9Sstevel@tonic-gate 		 * one of the parent lgroups somewhere along the line
9637c478bd9Sstevel@tonic-gate 		 */
9647c478bd9Sstevel@tonic-gate 		if (latency < parent->lgrp_latency) {
9657c478bd9Sstevel@tonic-gate 			lgrp_t	*intermed;
9667c478bd9Sstevel@tonic-gate 
9677c478bd9Sstevel@tonic-gate 			/*
9687c478bd9Sstevel@tonic-gate 			 * New leaf resources should go in between current
9697c478bd9Sstevel@tonic-gate 			 * child and parent
9707c478bd9Sstevel@tonic-gate 			 */
9717c478bd9Sstevel@tonic-gate #ifdef	DEBUG
9727c478bd9Sstevel@tonic-gate 			if (lgrp_topo_debug > 0)
9737c478bd9Sstevel@tonic-gate 				prom_printf("lgrp_lineage_add: "
9747c478bd9Sstevel@tonic-gate 				    "latency < parent latency\n");
9757c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 			/*
9787c478bd9Sstevel@tonic-gate 			 * Create lgroup with desired resources and insert it
9797c478bd9Sstevel@tonic-gate 			 * between child and parent
9807c478bd9Sstevel@tonic-gate 			 */
9817c478bd9Sstevel@tonic-gate 			lgrp_rsets_copy(child->lgrp_set, rset);
9827c478bd9Sstevel@tonic-gate 			lgrp_rsets_add(newleaf->lgrp_set, rset);
9837c478bd9Sstevel@tonic-gate 			if (nlevels >= lgrp_topo_levels) {
9842bf5f692SEthindra Ramamurthy 
9852bf5f692SEthindra Ramamurthy #ifdef	DEBUG
9862bf5f692SEthindra Ramamurthy 				if (lgrp_topo_debug > 0) {
9872bf5f692SEthindra Ramamurthy 					prom_printf("lgrp_lineage_add: nlevels "
9882bf5f692SEthindra Ramamurthy 					    "%d > lgrp_topo_levels %d\n",
9892bf5f692SEthindra Ramamurthy 					    nlevels, lgrp_topo_levels);
9902bf5f692SEthindra Ramamurthy 					lgrp_rsets_print("rset ", rset);
9912bf5f692SEthindra Ramamurthy 				}
9922bf5f692SEthindra Ramamurthy #endif	/* DEBUG */
9932bf5f692SEthindra Ramamurthy 
9942bf5f692SEthindra Ramamurthy 				if (parent == lgrp_root) {
9952bf5f692SEthindra Ramamurthy 					/*
9962bf5f692SEthindra Ramamurthy 					 * Don't proprogate new leaf resources
9972bf5f692SEthindra Ramamurthy 					 * to parent, if it already contains
9982bf5f692SEthindra Ramamurthy 					 * these resources
9992bf5f692SEthindra Ramamurthy 					 */
10002bf5f692SEthindra Ramamurthy 					if (lgrp_rsets_member_all(
10012bf5f692SEthindra Ramamurthy 					    parent->lgrp_set, newleaf->lgrp_id))
10022bf5f692SEthindra Ramamurthy 						break;
10032bf5f692SEthindra Ramamurthy 
10042bf5f692SEthindra Ramamurthy 					total += lgrp_proprogate(newleaf, child,
10052bf5f692SEthindra Ramamurthy 					    latency, &changes);
10067c478bd9Sstevel@tonic-gate 					break;
10072bf5f692SEthindra Ramamurthy 				}
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate #ifdef	DEBUG
10107c478bd9Sstevel@tonic-gate 				if (lgrp_topo_debug > 0) {
10117c478bd9Sstevel@tonic-gate 					prom_printf("lgrp_lineage_add: "
10127c478bd9Sstevel@tonic-gate 					    "replaced parent lgrp %d at 0x%p"
10137c478bd9Sstevel@tonic-gate 					    " for lgrp %d\n",
10148793b36bSNick Todd 					    parent->lgrp_id, (void *)parent,
10157c478bd9Sstevel@tonic-gate 					    child->lgrp_id);
10167c478bd9Sstevel@tonic-gate 					lgrp_rsets_print("old parent"
10177c478bd9Sstevel@tonic-gate 					    " resources:", parent->lgrp_set);
10187c478bd9Sstevel@tonic-gate 					lgrp_rsets_print("new parent "
10197c478bd9Sstevel@tonic-gate 					    "resources:", rset);
10207c478bd9Sstevel@tonic-gate 				}
10217c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
10227c478bd9Sstevel@tonic-gate 				/*
10237c478bd9Sstevel@tonic-gate 				 * Replace contents of parent with new
10247c478bd9Sstevel@tonic-gate 				 * leaf + child resources since new leaf is
10257c478bd9Sstevel@tonic-gate 				 * closer and shift its parent's resources to
10267c478bd9Sstevel@tonic-gate 				 * its parent, etc. until root lgroup reached
10277c478bd9Sstevel@tonic-gate 				 */
10287c478bd9Sstevel@tonic-gate 				lgrp_rsets_replace(rset, latency, parent, 1);
10297c478bd9Sstevel@tonic-gate 				if (*changed)
10307c478bd9Sstevel@tonic-gate 					klgrpset_or(*changed, parent->lgrp_id);
10317c478bd9Sstevel@tonic-gate 				total++;
10327c478bd9Sstevel@tonic-gate 				proprogate++;
10337c478bd9Sstevel@tonic-gate 			} else {
10342bf5f692SEthindra Ramamurthy 
10352bf5f692SEthindra Ramamurthy #ifdef	DEBUG
10362bf5f692SEthindra Ramamurthy 				if (lgrp_topo_debug > 0) {
10372bf5f692SEthindra Ramamurthy 					prom_printf("lgrp_lineage_add: "
10382bf5f692SEthindra Ramamurthy 					    "lgrp_new_parent(0x%p,%d)\n",
10392bf5f692SEthindra Ramamurthy 					    (void *)child, latency);
10402bf5f692SEthindra Ramamurthy 					lgrp_rsets_print("rset ", rset);
10412bf5f692SEthindra Ramamurthy 				}
10422bf5f692SEthindra Ramamurthy #endif	/* DEBUG */
10432bf5f692SEthindra Ramamurthy 
10447c478bd9Sstevel@tonic-gate 				total += lgrp_new_parent(child, latency, rset,
10457c478bd9Sstevel@tonic-gate 				    &changes);
10467c478bd9Sstevel@tonic-gate 				intermed = child->lgrp_parent;
10477c478bd9Sstevel@tonic-gate 				klgrpset_add(collapse, intermed->lgrp_id);
10487c478bd9Sstevel@tonic-gate 				if (changed)
10497c478bd9Sstevel@tonic-gate 					klgrpset_or(*changed, changes);
10507c478bd9Sstevel@tonic-gate 				child = intermed;
10517c478bd9Sstevel@tonic-gate 				proprogate++;
10527c478bd9Sstevel@tonic-gate #ifdef	DEBUG
10537c478bd9Sstevel@tonic-gate 				if (lgrp_topo_debug > 0) {
10547c478bd9Sstevel@tonic-gate 					prom_printf("lgrp_lineage_add: new "
10557c478bd9Sstevel@tonic-gate 					    "parent lgrp %d at 0x%p for "
10567c478bd9Sstevel@tonic-gate 					    "lgrp %d\n", intermed->lgrp_id,
10578793b36bSNick Todd 					    (void *)intermed, child->lgrp_id);
10587c478bd9Sstevel@tonic-gate 					lgrp_rsets_print("new parent "
10597c478bd9Sstevel@tonic-gate 					    "resources:", rset);
10607c478bd9Sstevel@tonic-gate 				}
10617c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
10627c478bd9Sstevel@tonic-gate 				continue;
10637c478bd9Sstevel@tonic-gate 			}
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate 		} else if (latency == parent->lgrp_latency) {
10667c478bd9Sstevel@tonic-gate 			/*
10677c478bd9Sstevel@tonic-gate 			 * New leaf resources should go into parent
10687c478bd9Sstevel@tonic-gate 			 */
10697c478bd9Sstevel@tonic-gate #ifdef	DEBUG
10707c478bd9Sstevel@tonic-gate 			if (lgrp_topo_debug > 0)
10717c478bd9Sstevel@tonic-gate 				prom_printf("lgrp_lineage_add: latency == "
10727c478bd9Sstevel@tonic-gate 				    "parent latency\n");
10737c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
10747c478bd9Sstevel@tonic-gate 
10757c478bd9Sstevel@tonic-gate 			/*
10767c478bd9Sstevel@tonic-gate 			 * It's already there, so don't need to do anything.
10777c478bd9Sstevel@tonic-gate 			 */
10787c478bd9Sstevel@tonic-gate 			if (lgrp_rsets_member_all(parent->lgrp_set,
10797c478bd9Sstevel@tonic-gate 			    newleaf->lgrp_id))
10807c478bd9Sstevel@tonic-gate 				break;
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 			total += lgrp_proprogate(newleaf, child, latency,
10837c478bd9Sstevel@tonic-gate 			    &changes);
10847c478bd9Sstevel@tonic-gate 			parent = child->lgrp_parent;
10857c478bd9Sstevel@tonic-gate 			klgrpset_add(collapse, parent->lgrp_id);
10867c478bd9Sstevel@tonic-gate 			if (changed)
10877c478bd9Sstevel@tonic-gate 				klgrpset_or(*changed, changes);
10887c478bd9Sstevel@tonic-gate 
10897c478bd9Sstevel@tonic-gate 			proprogate++;
10907c478bd9Sstevel@tonic-gate 		}
10917c478bd9Sstevel@tonic-gate 
10927c478bd9Sstevel@tonic-gate 		child = parent;
10937c478bd9Sstevel@tonic-gate 		parent = parent->lgrp_parent;
10947c478bd9Sstevel@tonic-gate 	} while (parent != NULL);
10957c478bd9Sstevel@tonic-gate 
10967c478bd9Sstevel@tonic-gate 	/*
10977c478bd9Sstevel@tonic-gate 	 * Consolidate any duplicate lgroups of ones just changed
10987c478bd9Sstevel@tonic-gate 	 * Assume that there were no duplicates before last round of changes
10997c478bd9Sstevel@tonic-gate 	 */
11007c478bd9Sstevel@tonic-gate #ifdef	DEBUG
11017c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
11027c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_lineage_add: collapsing dups....\n");
11037c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	total += lgrp_collapse_dups(collapse, lgrp_collapse_equidist,
11067c478bd9Sstevel@tonic-gate 	    &changes);
11077c478bd9Sstevel@tonic-gate 	if (changed)
11087c478bd9Sstevel@tonic-gate 		klgrpset_or(*changed, changes);
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate #ifdef	DEBUG
11117c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
11127c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_lineage_add: changed %d lgrps: 0x%llx\n",
11137c478bd9Sstevel@tonic-gate 		    total, (u_longlong_t)*changed);
11147c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	return (total);
11177c478bd9Sstevel@tonic-gate }
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate /*
11217c478bd9Sstevel@tonic-gate  * Add leaf lgroup to lgroup topology
11227c478bd9Sstevel@tonic-gate  */
11237c478bd9Sstevel@tonic-gate int
lgrp_leaf_add(lgrp_t * leaf,lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)11247c478bd9Sstevel@tonic-gate lgrp_leaf_add(lgrp_t *leaf, lgrp_t **lgrps, int lgrp_count,
11257c478bd9Sstevel@tonic-gate     klgrpset_t *changed)
11267c478bd9Sstevel@tonic-gate {
11277c478bd9Sstevel@tonic-gate 	klgrpset_t	changes;
11287c478bd9Sstevel@tonic-gate 	int		count;
11297c478bd9Sstevel@tonic-gate 	int		i;
11307c478bd9Sstevel@tonic-gate 	int		latency;
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 ||
11337c478bd9Sstevel@tonic-gate 	    !lgrp_initialized);
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate #ifdef	DEBUG
11367c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
11377c478bd9Sstevel@tonic-gate 		prom_printf("\nlgrp_leaf_add(0x%p[%d],0x%p,%d,0x%p)\n",
11388793b36bSNick Todd 		    (void *)leaf, leaf->lgrp_id, (void *)lgrps, lgrp_count,
11398793b36bSNick Todd 		    (void *)changed);
11407c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 	count = 0;
11437c478bd9Sstevel@tonic-gate 	if (changed)
11447c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
11457c478bd9Sstevel@tonic-gate 
11467c478bd9Sstevel@tonic-gate 	/*
11477c478bd9Sstevel@tonic-gate 	 * Initialize parent of leaf lgroup to root
11487c478bd9Sstevel@tonic-gate 	 */
11497c478bd9Sstevel@tonic-gate 	if (leaf->lgrp_parent == NULL) {
11507c478bd9Sstevel@tonic-gate 		leaf->lgrp_parent = lgrp_root;
11517c478bd9Sstevel@tonic-gate 		lgrp_root->lgrp_childcnt++;
11527c478bd9Sstevel@tonic-gate 		klgrpset_add(lgrp_root->lgrp_children, leaf->lgrp_id);
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate 		klgrpset_or(lgrp_root->lgrp_leaves, leaf->lgrp_leaves);
11557c478bd9Sstevel@tonic-gate 		lgrp_rsets_add(leaf->lgrp_set, lgrp_root->lgrp_set);
11567c478bd9Sstevel@tonic-gate 
11577c478bd9Sstevel@tonic-gate #ifdef	DEBUG
11587c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1)
11597c478bd9Sstevel@tonic-gate 			lgrp_rsets_print("lgrp_leaf_add: root lgrp resources",
11607c478bd9Sstevel@tonic-gate 			    lgrp_root->lgrp_set);
11617c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 		if (changed) {
11647c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, lgrp_root->lgrp_id);
11657c478bd9Sstevel@tonic-gate 			klgrpset_add(*changed, leaf->lgrp_id);
11667c478bd9Sstevel@tonic-gate 		}
11677c478bd9Sstevel@tonic-gate 		count += 2;
11687c478bd9Sstevel@tonic-gate 	}
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 	/*
11717c478bd9Sstevel@tonic-gate 	 * Can't add leaf lgroup to rest of topology (and vice versa) unless
11727c478bd9Sstevel@tonic-gate 	 * latency for it is available
11737c478bd9Sstevel@tonic-gate 	 */
11747c478bd9Sstevel@tonic-gate 	latency = lgrp_plat_latency(leaf->lgrp_plathand, leaf->lgrp_plathand);
11757c478bd9Sstevel@tonic-gate 	if (latency == 0) {
11767c478bd9Sstevel@tonic-gate #ifdef	DEBUG
11777c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
11787c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_leaf_add: changed %d lgrps: 0x%llx\n",
11797c478bd9Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
11807c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
11817c478bd9Sstevel@tonic-gate 		return (count);
11827c478bd9Sstevel@tonic-gate 	}
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	/*
11857c478bd9Sstevel@tonic-gate 	 * Make sure that root and leaf lgroup latencies are set
11867c478bd9Sstevel@tonic-gate 	 */
11877c478bd9Sstevel@tonic-gate 	lgrp_root->lgrp_latency = lgrp_plat_latency(lgrp_root->lgrp_plathand,
11887c478bd9Sstevel@tonic-gate 	    lgrp_root->lgrp_plathand);
11897c478bd9Sstevel@tonic-gate 	leaf->lgrp_latency = latency;
11907c478bd9Sstevel@tonic-gate 
11917c478bd9Sstevel@tonic-gate 	/*
11927c478bd9Sstevel@tonic-gate 	 * Add leaf to lineage of other leaves and vice versa
11937c478bd9Sstevel@tonic-gate 	 * since leaves come into existence at different times
11947c478bd9Sstevel@tonic-gate 	 */
11957c478bd9Sstevel@tonic-gate 	for (i = 0; i < lgrp_count; i++) {
11967c478bd9Sstevel@tonic-gate 		lgrp_t		*lgrp;
11977c478bd9Sstevel@tonic-gate 
11987c478bd9Sstevel@tonic-gate 		lgrp = lgrps[i];
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate 		/*
12017c478bd9Sstevel@tonic-gate 		 * Skip non-existent lgroups, new leaf lgroup, and
12027c478bd9Sstevel@tonic-gate 		 * non-leaf lgroups
12037c478bd9Sstevel@tonic-gate 		 */
12047c478bd9Sstevel@tonic-gate 		if (!LGRP_EXISTS(lgrp) || lgrp == leaf ||
12057c478bd9Sstevel@tonic-gate 		    lgrp->lgrp_childcnt != 0) {
12067c478bd9Sstevel@tonic-gate #ifdef	DEBUG
12077c478bd9Sstevel@tonic-gate 			if (lgrp_topo_debug > 1)
12087c478bd9Sstevel@tonic-gate 				prom_printf("lgrp_leaf_add: skip "
12097c478bd9Sstevel@tonic-gate 				    "lgrp %d at 0x%p\n",
12108793b36bSNick Todd 				    lgrp->lgrp_id, (void *)lgrp);
12117c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
12127c478bd9Sstevel@tonic-gate 			continue;
12137c478bd9Sstevel@tonic-gate 		}
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate #ifdef	DEBUG
12167c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
12177c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_leaf_add: lgrp %d (0x%p) =>"
12187c478bd9Sstevel@tonic-gate 			    " lgrp %d (0x%p)\n",
12198793b36bSNick Todd 			    leaf->lgrp_id, (void *)leaf, lgrp->lgrp_id,
12208793b36bSNick Todd 			    (void *)lgrp);
12217c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
12227c478bd9Sstevel@tonic-gate 
12237c478bd9Sstevel@tonic-gate 		count += lgrp_lineage_add(leaf, lgrp, &changes);
12247c478bd9Sstevel@tonic-gate 		if (changed)
12257c478bd9Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 		count += lgrp_lineage_add(lgrp, leaf, &changes);
12287c478bd9Sstevel@tonic-gate 		if (changed)
12297c478bd9Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
12307c478bd9Sstevel@tonic-gate 	}
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate #ifdef	DEBUG
12337c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
12347c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_leaf_add: changed %d lgrps: 0x%llx\n",
12357c478bd9Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
12367c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate 	return (count);
12397c478bd9Sstevel@tonic-gate }
12407c478bd9Sstevel@tonic-gate 
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate /*
12437c478bd9Sstevel@tonic-gate  * Remove resources of leaf from lgroup hierarchy
12447c478bd9Sstevel@tonic-gate  */
12457c478bd9Sstevel@tonic-gate int
lgrp_leaf_delete(lgrp_t * leaf,lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)12467c478bd9Sstevel@tonic-gate lgrp_leaf_delete(lgrp_t *leaf, lgrp_t **lgrps, int lgrp_count,
12477c478bd9Sstevel@tonic-gate     klgrpset_t *changed)
12487c478bd9Sstevel@tonic-gate {
12497c478bd9Sstevel@tonic-gate 	klgrpset_t	changes;
12507c478bd9Sstevel@tonic-gate 	klgrpset_t	collapse;
12517c478bd9Sstevel@tonic-gate 	int		count;
12527c478bd9Sstevel@tonic-gate 	int		i;
12537c478bd9Sstevel@tonic-gate 	lgrp_t		*lgrp;
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 ||
12567c478bd9Sstevel@tonic-gate 	    !lgrp_initialized);
12577c478bd9Sstevel@tonic-gate 
12587c478bd9Sstevel@tonic-gate 	count = 0;
12597c478bd9Sstevel@tonic-gate 	klgrpset_clear(collapse);
12607c478bd9Sstevel@tonic-gate 	if (changed)
12617c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
12627c478bd9Sstevel@tonic-gate 
12637c478bd9Sstevel@tonic-gate 	/*
12647c478bd9Sstevel@tonic-gate 	 * Nothing to do if no leaf given
12657c478bd9Sstevel@tonic-gate 	 */
12667c478bd9Sstevel@tonic-gate 	if (leaf == NULL)
12677c478bd9Sstevel@tonic-gate 		return (0);
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate #ifdef	DEBUG
12707c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 0)
12717c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete(0x%p[%d],0x%p,%d,0x%p)\n",
12728793b36bSNick Todd 		    (void *)leaf, leaf->lgrp_id, (void *)lgrps, lgrp_count,
12738793b36bSNick Todd 		    (void *)changed);
12747c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 	/*
12777c478bd9Sstevel@tonic-gate 	 * Remove leaf from any lgroups containing its resources
12787c478bd9Sstevel@tonic-gate 	 */
12797c478bd9Sstevel@tonic-gate 	for (i = 0; i < lgrp_count; i++) {
12807c478bd9Sstevel@tonic-gate 		lgrp = lgrps[i];
12817c478bd9Sstevel@tonic-gate 		if (lgrp == NULL || lgrp->lgrp_id == LGRP_NONE ||
12827c478bd9Sstevel@tonic-gate 		    !lgrp_rsets_member(lgrp->lgrp_set, leaf->lgrp_id))
12837c478bd9Sstevel@tonic-gate 			continue;
12847c478bd9Sstevel@tonic-gate 
12857c478bd9Sstevel@tonic-gate #ifdef	DEBUG
12867c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 0)
12877c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_leaf_delete: remove leaf from"
12888793b36bSNick Todd 			    " lgrp %d at %p\n", lgrp->lgrp_id, (void *)lgrp);
12897c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 		lgrp_rsets_delete(lgrp, leaf->lgrp_id, 0);
12927c478bd9Sstevel@tonic-gate 		klgrpset_del(lgrp->lgrp_leaves, leaf->lgrp_id);
12937c478bd9Sstevel@tonic-gate 
12947c478bd9Sstevel@tonic-gate 		klgrpset_add(collapse, lgrp->lgrp_id);
12957c478bd9Sstevel@tonic-gate 		count++;
12967c478bd9Sstevel@tonic-gate 	}
12977c478bd9Sstevel@tonic-gate 
12987c478bd9Sstevel@tonic-gate 	/*
12997c478bd9Sstevel@tonic-gate 	 * Remove leaf and its ancestors that don't have any other children
13007c478bd9Sstevel@tonic-gate 	 */
13017c478bd9Sstevel@tonic-gate #ifdef	DEBUG
13027c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
13037c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete: remove leaf and ancestors\n");
13047c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
13057c478bd9Sstevel@tonic-gate 
13067c478bd9Sstevel@tonic-gate 	count += lgrp_ancestor_delete(leaf, &changes);
13077c478bd9Sstevel@tonic-gate 	klgrpset_or(collapse, changes);
13087c478bd9Sstevel@tonic-gate 	klgrpset_add(collapse, leaf->lgrp_id);
13097c478bd9Sstevel@tonic-gate 	count++;
13107c478bd9Sstevel@tonic-gate 	lgrp_destroy(leaf);
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate 	/*
13137c478bd9Sstevel@tonic-gate 	 * Consolidate any duplicate lgroups of ones just changed
13147c478bd9Sstevel@tonic-gate 	 * Assume that there were no duplicates before last round of changes
13157c478bd9Sstevel@tonic-gate 	 */
13167c478bd9Sstevel@tonic-gate #ifdef	DEBUG
13177c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1)
13187c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete: collapsing dups\n");
13197c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
13207c478bd9Sstevel@tonic-gate 	count += lgrp_collapse_dups(collapse, lgrp_collapse_equidist,
13217c478bd9Sstevel@tonic-gate 	    &changes);
13227c478bd9Sstevel@tonic-gate 	klgrpset_or(collapse, changes);
13237c478bd9Sstevel@tonic-gate 	if (changed)
13247c478bd9Sstevel@tonic-gate 		klgrpset_copy(*changed, collapse);
13257c478bd9Sstevel@tonic-gate 
13267c478bd9Sstevel@tonic-gate #ifdef	DEBUG
13277c478bd9Sstevel@tonic-gate 	if (lgrp_topo_debug > 1 && changed)
13287c478bd9Sstevel@tonic-gate 		prom_printf("lgrp_leaf_delete: changed %d lgrps: 0x%llx\n",
13297c478bd9Sstevel@tonic-gate 		    count, (u_longlong_t)*changed);
13307c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
13317c478bd9Sstevel@tonic-gate 
13327c478bd9Sstevel@tonic-gate 	return (count);
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate 
13357c478bd9Sstevel@tonic-gate 
13367c478bd9Sstevel@tonic-gate /*
13377c478bd9Sstevel@tonic-gate  * Flatten lgroup topology down to height specified
13387c478bd9Sstevel@tonic-gate  */
13397c478bd9Sstevel@tonic-gate int
lgrp_topo_flatten(int levels,lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)13407c478bd9Sstevel@tonic-gate lgrp_topo_flatten(int levels, lgrp_t **lgrps, int lgrp_count,
13417c478bd9Sstevel@tonic-gate     klgrpset_t *changed)
13427c478bd9Sstevel@tonic-gate {
13437c478bd9Sstevel@tonic-gate 	int	count;
13447c478bd9Sstevel@tonic-gate 	int	i;
13457c478bd9Sstevel@tonic-gate 	lgrp_t	*lgrp;
1346950a2babSrv 	lgrp_handle_t hdl;
13477c478bd9Sstevel@tonic-gate 
13487c478bd9Sstevel@tonic-gate 	/*
13497c478bd9Sstevel@tonic-gate 	 * Only flatten down to 2 level for now
13507c478bd9Sstevel@tonic-gate 	 */
13517c478bd9Sstevel@tonic-gate 	if (levels != 2)
13527c478bd9Sstevel@tonic-gate 		return (0);
13537c478bd9Sstevel@tonic-gate 
13547c478bd9Sstevel@tonic-gate 	/*
13557c478bd9Sstevel@tonic-gate 	 * Look for non-leaf lgroups to remove and leaf lgroups to reparent
13567c478bd9Sstevel@tonic-gate 	 */
13577c478bd9Sstevel@tonic-gate 	count = 0;
13587c478bd9Sstevel@tonic-gate 	for (i = 0; i <= lgrp_count; i++) {
13597c478bd9Sstevel@tonic-gate 		/*
13607c478bd9Sstevel@tonic-gate 		 * Skip non-existent lgroups and root
13617c478bd9Sstevel@tonic-gate 		 */
13627c478bd9Sstevel@tonic-gate 		lgrp = lgrps[i];
13631efae1c0Srv 		if (!LGRP_EXISTS(lgrp))
13647c478bd9Sstevel@tonic-gate 			continue;
13657c478bd9Sstevel@tonic-gate 
1366950a2babSrv 		hdl = lgrp->lgrp_plathand;
1367950a2babSrv 
1368950a2babSrv 		if (lgrp == lgrp_root) {
1369950a2babSrv 			lgrp->lgrp_latency = lgrp_plat_latency(hdl, hdl);
13701efae1c0Srv 			continue;
13711efae1c0Srv 		}
13721efae1c0Srv 
13737c478bd9Sstevel@tonic-gate 		if (lgrp->lgrp_childcnt > 0) {
13747c478bd9Sstevel@tonic-gate 			lgrp_t	*parent;
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate 			/*
13777c478bd9Sstevel@tonic-gate 			 * Remove non-leaf lgroup from lgroup topology
13787c478bd9Sstevel@tonic-gate 			 */
13797c478bd9Sstevel@tonic-gate 			parent = lgrp->lgrp_parent;
13807c478bd9Sstevel@tonic-gate 			if (changed) {
13817c478bd9Sstevel@tonic-gate 				klgrpset_add(*changed, lgrp->lgrp_id);
13827c478bd9Sstevel@tonic-gate 				klgrpset_add(*changed, parent->lgrp_id);
13837c478bd9Sstevel@tonic-gate 				count += 2;
13847c478bd9Sstevel@tonic-gate 			}
13857c478bd9Sstevel@tonic-gate 			if (parent) {
13867c478bd9Sstevel@tonic-gate 				klgrpset_del(parent->lgrp_children,
13877c478bd9Sstevel@tonic-gate 				    lgrp->lgrp_id);
13887c478bd9Sstevel@tonic-gate 				parent->lgrp_childcnt--;
13897c478bd9Sstevel@tonic-gate 			}
13907c478bd9Sstevel@tonic-gate 			lgrp_destroy(lgrp);
13917c478bd9Sstevel@tonic-gate 		} else if (lgrp->lgrp_parent != lgrp_root) {
13927c478bd9Sstevel@tonic-gate 			/*
13937c478bd9Sstevel@tonic-gate 			 * Reparent leaf lgroup to root
13947c478bd9Sstevel@tonic-gate 			 */
13957c478bd9Sstevel@tonic-gate 			if (changed) {
13967c478bd9Sstevel@tonic-gate 				klgrpset_add(*changed, lgrp_root->lgrp_id);
13977c478bd9Sstevel@tonic-gate 				klgrpset_add(*changed, lgrp->lgrp_id);
13987c478bd9Sstevel@tonic-gate 				count += 2;
13997c478bd9Sstevel@tonic-gate 			}
14007c478bd9Sstevel@tonic-gate 			lgrp->lgrp_parent = lgrp_root;
14017c478bd9Sstevel@tonic-gate 			klgrpset_add(lgrp_root->lgrp_children, lgrp->lgrp_id);
14027c478bd9Sstevel@tonic-gate 			lgrp_root->lgrp_childcnt++;
14037c478bd9Sstevel@tonic-gate 			klgrpset_add(lgrp_root->lgrp_leaves, lgrp->lgrp_id);
14041efae1c0Srv 
1405950a2babSrv 			lgrp->lgrp_latency = lgrp_plat_latency(hdl, hdl);
14067c478bd9Sstevel@tonic-gate 		}
14077c478bd9Sstevel@tonic-gate 	}
14087c478bd9Sstevel@tonic-gate 
14097c478bd9Sstevel@tonic-gate 	return (count);
14107c478bd9Sstevel@tonic-gate }
14117c478bd9Sstevel@tonic-gate 
14127c478bd9Sstevel@tonic-gate 
14137c478bd9Sstevel@tonic-gate /*
14147c478bd9Sstevel@tonic-gate  * Return current height limit for lgroup topology
14157c478bd9Sstevel@tonic-gate  */
14167c478bd9Sstevel@tonic-gate int
lgrp_topo_ht_limit(void)14177c478bd9Sstevel@tonic-gate lgrp_topo_ht_limit(void)
14187c478bd9Sstevel@tonic-gate {
14197c478bd9Sstevel@tonic-gate 	return (lgrp_topo_levels);
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 
14237c478bd9Sstevel@tonic-gate /*
14247c478bd9Sstevel@tonic-gate  * Return default height limit for lgroup topology
14257c478bd9Sstevel@tonic-gate  */
14267c478bd9Sstevel@tonic-gate int
lgrp_topo_ht_limit_default(void)14277c478bd9Sstevel@tonic-gate lgrp_topo_ht_limit_default(void)
14287c478bd9Sstevel@tonic-gate {
14297c478bd9Sstevel@tonic-gate 	return (LGRP_TOPO_LEVELS);
14307c478bd9Sstevel@tonic-gate }
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate /*
14347c478bd9Sstevel@tonic-gate  * Set height limit for lgroup topology
14357c478bd9Sstevel@tonic-gate  */
14367c478bd9Sstevel@tonic-gate int
lgrp_topo_ht_limit_set(int ht)14377c478bd9Sstevel@tonic-gate lgrp_topo_ht_limit_set(int ht)
14387c478bd9Sstevel@tonic-gate {
14397c478bd9Sstevel@tonic-gate 	if (ht > LGRP_TOPO_LEVELS_MAX)
14407c478bd9Sstevel@tonic-gate 		lgrp_topo_levels = LGRP_TOPO_LEVELS_MAX;
14417c478bd9Sstevel@tonic-gate 	else
14427c478bd9Sstevel@tonic-gate 		lgrp_topo_levels = ht;
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 	return (ht);
14457c478bd9Sstevel@tonic-gate }
14467c478bd9Sstevel@tonic-gate 
14477c478bd9Sstevel@tonic-gate 
14487c478bd9Sstevel@tonic-gate /*
14497c478bd9Sstevel@tonic-gate  * Update lgroup topology for any leaves that don't have their latency set
14507c478bd9Sstevel@tonic-gate  *
14517c478bd9Sstevel@tonic-gate  * This may happen on some machines when the lgroup platform support doesn't
14527c478bd9Sstevel@tonic-gate  * know the latencies between nodes soon enough to provide it when the
14537c478bd9Sstevel@tonic-gate  * resources are being added.  If the lgroup platform code needs to probe
14547c478bd9Sstevel@tonic-gate  * memory to determine the latencies between nodes, it must wait until the
14557c478bd9Sstevel@tonic-gate  * CPUs become active so at least one CPU in each node can probe memory in
14567c478bd9Sstevel@tonic-gate  * each node.
14577c478bd9Sstevel@tonic-gate  */
14587c478bd9Sstevel@tonic-gate int
lgrp_topo_update(lgrp_t ** lgrps,int lgrp_count,klgrpset_t * changed)14597c478bd9Sstevel@tonic-gate lgrp_topo_update(lgrp_t **lgrps, int lgrp_count, klgrpset_t *changed)
14607c478bd9Sstevel@tonic-gate {
14617c478bd9Sstevel@tonic-gate 	klgrpset_t	changes;
14627c478bd9Sstevel@tonic-gate 	int		count;
14637c478bd9Sstevel@tonic-gate 	int		i;
14647c478bd9Sstevel@tonic-gate 	lgrp_t		*lgrp;
14657c478bd9Sstevel@tonic-gate 
14667c478bd9Sstevel@tonic-gate 	count = 0;
14677c478bd9Sstevel@tonic-gate 	if (changed)
14687c478bd9Sstevel@tonic-gate 		klgrpset_clear(*changed);
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 	/*
14717c478bd9Sstevel@tonic-gate 	 * For UMA machines, make sure that root lgroup contains all
14727c478bd9Sstevel@tonic-gate 	 * resources.  The root lgrp should also name itself as its own leaf
14737c478bd9Sstevel@tonic-gate 	 */
14747c478bd9Sstevel@tonic-gate 	if (nlgrps == 1) {
14757c478bd9Sstevel@tonic-gate 		for (i = 0; i < LGRP_RSRC_COUNT; i++)
14767c478bd9Sstevel@tonic-gate 			klgrpset_add(lgrp_root->lgrp_set[i],
14777c478bd9Sstevel@tonic-gate 			    lgrp_root->lgrp_id);
14787c478bd9Sstevel@tonic-gate 		klgrpset_add(lgrp_root->lgrp_leaves, lgrp_root->lgrp_id);
14797c478bd9Sstevel@tonic-gate 		return (0);
14807c478bd9Sstevel@tonic-gate 	}
14817c478bd9Sstevel@tonic-gate 
14827c478bd9Sstevel@tonic-gate 	mutex_enter(&cpu_lock);
1483*0ed5c46eSJosef 'Jeff' Sipek 	pause_cpus(NULL, NULL);
14847c478bd9Sstevel@tonic-gate 
14857c478bd9Sstevel@tonic-gate 	/*
14867c478bd9Sstevel@tonic-gate 	 * Look for any leaf lgroup without its latency set, finish adding it
14877c478bd9Sstevel@tonic-gate 	 * to the lgroup topology assuming that it exists and has the root
14887c478bd9Sstevel@tonic-gate 	 * lgroup as its parent, and update the memory nodes of all lgroups
14897c478bd9Sstevel@tonic-gate 	 * that have it as a memory resource.
14907c478bd9Sstevel@tonic-gate 	 */
14917c478bd9Sstevel@tonic-gate 	for (i = 0; i < lgrp_count; i++) {
14927c478bd9Sstevel@tonic-gate 		lgrp = lgrps[i];
14937c478bd9Sstevel@tonic-gate 
14947c478bd9Sstevel@tonic-gate 		/*
14957c478bd9Sstevel@tonic-gate 		 * Skip non-existent and non-leaf lgroups and any lgroup
14967c478bd9Sstevel@tonic-gate 		 * with its latency set already
14977c478bd9Sstevel@tonic-gate 		 */
14987c478bd9Sstevel@tonic-gate 		if (lgrp == NULL || lgrp->lgrp_id == LGRP_NONE ||
14997c478bd9Sstevel@tonic-gate 		    lgrp->lgrp_childcnt != 0 || lgrp->lgrp_latency != 0)
15007c478bd9Sstevel@tonic-gate 			continue;
15017c478bd9Sstevel@tonic-gate 
15027c478bd9Sstevel@tonic-gate #ifdef	DEBUG
15037c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1) {
15047c478bd9Sstevel@tonic-gate 			prom_printf("\nlgrp_topo_update: updating lineage "
15058793b36bSNick Todd 			    "of lgrp %d at 0x%p\n", lgrp->lgrp_id,
15068793b36bSNick Todd 			    (void *)lgrp);
15077c478bd9Sstevel@tonic-gate 		}
15087c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
15097c478bd9Sstevel@tonic-gate 
15107c478bd9Sstevel@tonic-gate 		count += lgrp_leaf_add(lgrp, lgrps, lgrp_count, &changes);
15117c478bd9Sstevel@tonic-gate 		if (changed)
15127c478bd9Sstevel@tonic-gate 			klgrpset_or(*changed, changes);
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate 		if (!klgrpset_isempty(changes))
15157c478bd9Sstevel@tonic-gate 			(void) lgrp_mnode_update(changes, NULL);
15167c478bd9Sstevel@tonic-gate 
15177c478bd9Sstevel@tonic-gate #ifdef	DEBUG
15187c478bd9Sstevel@tonic-gate 		if (lgrp_topo_debug > 1 && changed)
15197c478bd9Sstevel@tonic-gate 			prom_printf("lgrp_topo_update: changed %d lgrps: "
15207c478bd9Sstevel@tonic-gate 			    "0x%llx\n",
15217c478bd9Sstevel@tonic-gate 			    count, (u_longlong_t)*changed);
15227c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
15237c478bd9Sstevel@tonic-gate 	}
15247c478bd9Sstevel@tonic-gate 
15257c478bd9Sstevel@tonic-gate 	if (lgrp_topo_levels < LGRP_TOPO_LEVELS && lgrp_topo_levels == 2) {
15267c478bd9Sstevel@tonic-gate 		count += lgrp_topo_flatten(2, lgrps, lgrp_count, changed);
15277c478bd9Sstevel@tonic-gate 		(void) lpl_topo_flatten(2);
15287c478bd9Sstevel@tonic-gate 	}
15297c478bd9Sstevel@tonic-gate 
15307c478bd9Sstevel@tonic-gate 	start_cpus();
15317c478bd9Sstevel@tonic-gate 	mutex_exit(&cpu_lock);
15327c478bd9Sstevel@tonic-gate 
15337c478bd9Sstevel@tonic-gate 	return (count);
15347c478bd9Sstevel@tonic-gate }
15357c478bd9Sstevel@tonic-gate 
15367c478bd9Sstevel@tonic-gate #ifdef	DEBUG
15377c478bd9Sstevel@tonic-gate void
lgrp_print(lgrp_t * lgrp)15387c478bd9Sstevel@tonic-gate lgrp_print(lgrp_t *lgrp)
15397c478bd9Sstevel@tonic-gate {
15407c478bd9Sstevel@tonic-gate 	lgrp_t	*parent;
15417c478bd9Sstevel@tonic-gate 
15427c478bd9Sstevel@tonic-gate 	prom_printf("LGRP %d", lgrp->lgrp_id);
15437c478bd9Sstevel@tonic-gate 	if (lgrp->lgrp_childcnt == 0)
15447c478bd9Sstevel@tonic-gate 		prom_printf(" (plathand %p)\n",
15457c478bd9Sstevel@tonic-gate 		    (void *)lgrp->lgrp_plathand);
15467c478bd9Sstevel@tonic-gate 	else
15477c478bd9Sstevel@tonic-gate 		prom_printf("\n");
15487c478bd9Sstevel@tonic-gate 
15497c478bd9Sstevel@tonic-gate 	prom_printf("\tlatency %d\n", lgrp->lgrp_latency);
15507c478bd9Sstevel@tonic-gate 
15517c478bd9Sstevel@tonic-gate 	lgrp_rsets_print("\tresources", lgrp->lgrp_set);
15527c478bd9Sstevel@tonic-gate 
15537c478bd9Sstevel@tonic-gate 	parent = lgrp->lgrp_parent;
15548793b36bSNick Todd 	prom_printf("\tparent 0x%p", (void *)parent);
15557c478bd9Sstevel@tonic-gate 	if (parent)
15567c478bd9Sstevel@tonic-gate 		prom_printf("[%d]\n", parent->lgrp_id);
15577c478bd9Sstevel@tonic-gate 	else
15587c478bd9Sstevel@tonic-gate 		prom_printf("\n");
15597c478bd9Sstevel@tonic-gate 
15607c478bd9Sstevel@tonic-gate 	prom_printf("\tchild count %d, children ", lgrp->lgrp_childcnt);
15617c478bd9Sstevel@tonic-gate 	klgrpset_print(lgrp->lgrp_children);
15627c478bd9Sstevel@tonic-gate 
15637c478bd9Sstevel@tonic-gate 	prom_printf("\tleaves ");
15647c478bd9Sstevel@tonic-gate 	klgrpset_print(lgrp->lgrp_leaves);
15657c478bd9Sstevel@tonic-gate }
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate 
15687c478bd9Sstevel@tonic-gate void
lgrp_topo_print(lgrp_t ** lgrps,int lgrp_max)15697c478bd9Sstevel@tonic-gate lgrp_topo_print(lgrp_t **lgrps, int lgrp_max)
15707c478bd9Sstevel@tonic-gate {
15717c478bd9Sstevel@tonic-gate 	klgrpset_t	siblings;
15727c478bd9Sstevel@tonic-gate 
15737c478bd9Sstevel@tonic-gate 	lgrp_print(lgrp_root);
15747c478bd9Sstevel@tonic-gate 	siblings = lgrp_root->lgrp_children;
15757c478bd9Sstevel@tonic-gate 	while (!klgrpset_isempty(siblings)) {
15767c478bd9Sstevel@tonic-gate 		klgrpset_t	children;
15777c478bd9Sstevel@tonic-gate 		int		i;
15787c478bd9Sstevel@tonic-gate 
15797c478bd9Sstevel@tonic-gate 		klgrpset_clear(children);
15807c478bd9Sstevel@tonic-gate 		for (i = 0; i <= lgrp_max; i++) {
15817c478bd9Sstevel@tonic-gate 			lgrp_t	*lgrp;
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate 			lgrp = lgrps[i];
15847c478bd9Sstevel@tonic-gate 			if (lgrp == NULL || !klgrpset_ismember(siblings, i))
15857c478bd9Sstevel@tonic-gate 				continue;
15867c478bd9Sstevel@tonic-gate 			lgrp_print(lgrp);
15877c478bd9Sstevel@tonic-gate 			klgrpset_or(children, lgrp->lgrp_children);
15887c478bd9Sstevel@tonic-gate 		}
15897c478bd9Sstevel@tonic-gate 		klgrpset_copy(siblings, children);
15907c478bd9Sstevel@tonic-gate 	}
15917c478bd9Sstevel@tonic-gate }
15927c478bd9Sstevel@tonic-gate #endif	/* DEBUG */
1593