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