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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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