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
5950a2babSrv207048 * Common Development and Distribution License (the "License").
6950a2babSrv207048 * 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))
10027c478bd9Sstevel@tonic-gate break;
10037c478bd9Sstevel@tonic-gate
10042bf5f692SEthindra Ramamurthy total += lgrp_proprogate(newleaf, child,
10052bf5f692SEthindra Ramamurthy latency, &changes);
10062bf5f692SEthindra Ramamurthy break;
10072bf5f692SEthindra Ramamurthy }
10082bf5f692SEthindra Ramamurthy
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;
1346950a2babSrv207048 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];
13631efae1c0Srv207048 if (!LGRP_EXISTS(lgrp))
13647c478bd9Sstevel@tonic-gate continue;
13657c478bd9Sstevel@tonic-gate
1366950a2babSrv207048 hdl = lgrp->lgrp_plathand;
1367950a2babSrv207048
13681efae1c0Srv207048 if (lgrp == lgrp_root) {
1369950a2babSrv207048 lgrp->lgrp_latency = lgrp_plat_latency(hdl, hdl);
13701efae1c0Srv207048 continue;
13711efae1c0Srv207048 }
13721efae1c0Srv207048
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);
14041efae1c0Srv207048
1405950a2babSrv207048 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