1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * lgroup topology 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate 33*0Sstevel@tonic-gate #include <sys/cpupart.h> 34*0Sstevel@tonic-gate #include <sys/lgrp.h> 35*0Sstevel@tonic-gate #include <sys/promif.h> 36*0Sstevel@tonic-gate #include <sys/types.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #define LGRP_TOPO_LEVELS 4 /* default height limit */ 40*0Sstevel@tonic-gate #define LGRP_TOPO_LEVELS_MAX 4 /* max height limit */ 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate /* 44*0Sstevel@tonic-gate * Only collapse lgroups which have same latency (and resources) 45*0Sstevel@tonic-gate */ 46*0Sstevel@tonic-gate int lgrp_collapse_equidist = 1; 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate int lgrp_collapse_off = 1; /* disable collapsing of duplicates */ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* 51*0Sstevel@tonic-gate * Height to limit lgroup topology 52*0Sstevel@tonic-gate */ 53*0Sstevel@tonic-gate unsigned int lgrp_topo_levels = LGRP_TOPO_LEVELS; 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate int lgrp_split_off = 1; /* disable splitting lgroups */ 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate #ifdef DEBUG 58*0Sstevel@tonic-gate /* 59*0Sstevel@tonic-gate * Debugging output 60*0Sstevel@tonic-gate * - 0: off 61*0Sstevel@tonic-gate * - >0: on and bigger means more 62*0Sstevel@tonic-gate */ 63*0Sstevel@tonic-gate int lgrp_topo_debug = 0; 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate void 67*0Sstevel@tonic-gate klgrpset_print(klgrpset_t lgrpset) 68*0Sstevel@tonic-gate { 69*0Sstevel@tonic-gate int i; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate prom_printf("0x%llx(", (u_longlong_t)lgrpset); 73*0Sstevel@tonic-gate for (i = 0; i <= lgrp_alloc_max; i++) 74*0Sstevel@tonic-gate if (klgrpset_ismember(lgrpset, i)) 75*0Sstevel@tonic-gate prom_printf("%d ", i); 76*0Sstevel@tonic-gate prom_printf(")\n"); 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate 80*0Sstevel@tonic-gate void 81*0Sstevel@tonic-gate lgrp_rsets_print(char *string, klgrpset_t *rsets) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate int i; 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate prom_printf("%s\n", string); 86*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 87*0Sstevel@tonic-gate klgrpset_print(rsets[i]); 88*0Sstevel@tonic-gate } 89*0Sstevel@tonic-gate #endif /* DEBUG */ 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate /* 93*0Sstevel@tonic-gate * Add "from" lgroup resources to "to" lgroup resources 94*0Sstevel@tonic-gate */ 95*0Sstevel@tonic-gate void 96*0Sstevel@tonic-gate lgrp_rsets_add(klgrpset_t *from, klgrpset_t *to) 97*0Sstevel@tonic-gate { 98*0Sstevel@tonic-gate int i; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 101*0Sstevel@tonic-gate klgrpset_or(to[i], from[i]); 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* 106*0Sstevel@tonic-gate * Copy "from" lgroup resources to "to" lgroup resources 107*0Sstevel@tonic-gate */ 108*0Sstevel@tonic-gate void 109*0Sstevel@tonic-gate lgrp_rsets_copy(klgrpset_t *from, klgrpset_t *to) 110*0Sstevel@tonic-gate { 111*0Sstevel@tonic-gate int i; 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 114*0Sstevel@tonic-gate to[i] = from[i]; 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * Delete given lgroup ID from lgroup resource set of specified lgroup 120*0Sstevel@tonic-gate * and its ancestors if "follow_parent" is set 121*0Sstevel@tonic-gate */ 122*0Sstevel@tonic-gate void 123*0Sstevel@tonic-gate lgrp_rsets_delete(lgrp_t *lgrp, lgrp_id_t lgrpid, int follow_parent) 124*0Sstevel@tonic-gate { 125*0Sstevel@tonic-gate int i; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate while (lgrp != NULL) { 128*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 129*0Sstevel@tonic-gate klgrpset_del(lgrp->lgrp_set[i], lgrpid); 130*0Sstevel@tonic-gate if (!follow_parent) 131*0Sstevel@tonic-gate break; 132*0Sstevel@tonic-gate lgrp = lgrp->lgrp_parent; 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate /* 138*0Sstevel@tonic-gate * Return whether given lgroup resource set empty 139*0Sstevel@tonic-gate */ 140*0Sstevel@tonic-gate int 141*0Sstevel@tonic-gate lgrp_rsets_empty(klgrpset_t *rset) 142*0Sstevel@tonic-gate { 143*0Sstevel@tonic-gate int i; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 146*0Sstevel@tonic-gate if (!klgrpset_isempty(rset[i])) 147*0Sstevel@tonic-gate return (0); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate return (1); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * Return whether given lgroup resource sets are same 155*0Sstevel@tonic-gate */ 156*0Sstevel@tonic-gate int 157*0Sstevel@tonic-gate lgrp_rsets_equal(klgrpset_t *rset1, klgrpset_t *rset2) 158*0Sstevel@tonic-gate { 159*0Sstevel@tonic-gate int i; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 162*0Sstevel@tonic-gate if (rset1[i] != rset2[i]) 163*0Sstevel@tonic-gate return (0); 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate return (1); 166*0Sstevel@tonic-gate } 167*0Sstevel@tonic-gate 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate /* 170*0Sstevel@tonic-gate * Return whether specified lgroup ID is in given lgroup resource set 171*0Sstevel@tonic-gate */ 172*0Sstevel@tonic-gate int 173*0Sstevel@tonic-gate lgrp_rsets_member(klgrpset_t *rset, lgrp_id_t lgrpid) 174*0Sstevel@tonic-gate { 175*0Sstevel@tonic-gate int i; 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 178*0Sstevel@tonic-gate if (klgrpset_ismember(rset[i], lgrpid)) 179*0Sstevel@tonic-gate return (1); 180*0Sstevel@tonic-gate 181*0Sstevel@tonic-gate return (0); 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate /* 186*0Sstevel@tonic-gate * Return whether specified lgroup ID is in all lgroup resources 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate int 189*0Sstevel@tonic-gate lgrp_rsets_member_all(klgrpset_t *rset, lgrp_id_t lgrpid) 190*0Sstevel@tonic-gate { 191*0Sstevel@tonic-gate int i; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 194*0Sstevel@tonic-gate if (!klgrpset_ismember(rset[i], lgrpid)) 195*0Sstevel@tonic-gate return (0); 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate return (1); 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate /* 202*0Sstevel@tonic-gate * Replace resources for given lgroup with specified resources at given 203*0Sstevel@tonic-gate * latency and shift its old resources to its parent and its parent's resources 204*0Sstevel@tonic-gate * to its parent, etc. until root lgroup reached 205*0Sstevel@tonic-gate */ 206*0Sstevel@tonic-gate void 207*0Sstevel@tonic-gate lgrp_rsets_replace(klgrpset_t *rset, int latency, lgrp_t *lgrp, int shift) 208*0Sstevel@tonic-gate { 209*0Sstevel@tonic-gate lgrp_t *cur; 210*0Sstevel@tonic-gate int lat_new; 211*0Sstevel@tonic-gate int lat_saved; 212*0Sstevel@tonic-gate klgrpset_t rset_new[LGRP_RSRC_COUNT]; 213*0Sstevel@tonic-gate klgrpset_t rset_saved[LGRP_RSRC_COUNT]; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate cur = lgrp; 216*0Sstevel@tonic-gate lat_saved = latency; 217*0Sstevel@tonic-gate lgrp_rsets_copy(rset, rset_saved); 218*0Sstevel@tonic-gate while (cur && cur != lgrp_root) { 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * Save current resources and latency to insert in parent and 221*0Sstevel@tonic-gate * then replace with new resources and latency 222*0Sstevel@tonic-gate */ 223*0Sstevel@tonic-gate lgrp_rsets_copy(rset_saved, rset_new); 224*0Sstevel@tonic-gate lgrp_rsets_copy(cur->lgrp_set, rset_saved); 225*0Sstevel@tonic-gate lgrp_rsets_copy(rset_new, cur->lgrp_set); 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate lat_new = lat_saved; 228*0Sstevel@tonic-gate lat_saved = cur->lgrp_latency; 229*0Sstevel@tonic-gate cur->lgrp_latency = lat_new; 230*0Sstevel@tonic-gate if (!shift) 231*0Sstevel@tonic-gate break; 232*0Sstevel@tonic-gate cur = cur->lgrp_parent; 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate /* 238*0Sstevel@tonic-gate * Set "to" lgroup resource set with given lgroup ID 239*0Sstevel@tonic-gate */ 240*0Sstevel@tonic-gate void 241*0Sstevel@tonic-gate lgrp_rsets_set(klgrpset_t *to, lgrp_id_t lgrpid) 242*0Sstevel@tonic-gate { 243*0Sstevel@tonic-gate klgrpset_t from; 244*0Sstevel@tonic-gate int i; 245*0Sstevel@tonic-gate 246*0Sstevel@tonic-gate klgrpset_clear(from); 247*0Sstevel@tonic-gate klgrpset_add(from, lgrpid); 248*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) { 249*0Sstevel@tonic-gate klgrpset_clear(to[i]); 250*0Sstevel@tonic-gate klgrpset_or(to[i], from); 251*0Sstevel@tonic-gate } 252*0Sstevel@tonic-gate } 253*0Sstevel@tonic-gate 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate /* 256*0Sstevel@tonic-gate * Delete any ancestors of given child lgroup which don't have any other 257*0Sstevel@tonic-gate * children 258*0Sstevel@tonic-gate */ 259*0Sstevel@tonic-gate int 260*0Sstevel@tonic-gate lgrp_ancestor_delete(lgrp_t *child, klgrpset_t *changed) 261*0Sstevel@tonic-gate { 262*0Sstevel@tonic-gate int count; 263*0Sstevel@tonic-gate lgrp_t *current; 264*0Sstevel@tonic-gate lgrp_id_t lgrpid; 265*0Sstevel@tonic-gate lgrp_t *parent; 266*0Sstevel@tonic-gate 267*0Sstevel@tonic-gate #ifdef DEBUG 268*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) { 269*0Sstevel@tonic-gate prom_printf("lgrp_ancestor_delete(0x%p[%d],0x%p)\n", 270*0Sstevel@tonic-gate child, child->lgrp_id, changed); 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate #endif /* DEBUG */ 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate count = 0; 275*0Sstevel@tonic-gate if (changed) 276*0Sstevel@tonic-gate klgrpset_clear(*changed); 277*0Sstevel@tonic-gate 278*0Sstevel@tonic-gate /* 279*0Sstevel@tonic-gate * Visit ancestors, decrement child count for each, and remove any 280*0Sstevel@tonic-gate * that don't have any children left until we reach an ancestor that 281*0Sstevel@tonic-gate * has multiple children 282*0Sstevel@tonic-gate */ 283*0Sstevel@tonic-gate current = child; 284*0Sstevel@tonic-gate parent = child->lgrp_parent; 285*0Sstevel@tonic-gate lgrpid = current->lgrp_id; 286*0Sstevel@tonic-gate while (parent != NULL) { 287*0Sstevel@tonic-gate #ifdef DEBUG 288*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 289*0Sstevel@tonic-gate prom_printf("lgrp_ancestor_delete: parent %d," 290*0Sstevel@tonic-gate " current %d\n", 291*0Sstevel@tonic-gate parent->lgrp_id, lgrpid); 292*0Sstevel@tonic-gate #endif /* DEBUG */ 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate klgrpset_del(parent->lgrp_leaves, lgrpid); 295*0Sstevel@tonic-gate klgrpset_del(parent->lgrp_children, lgrpid); 296*0Sstevel@tonic-gate parent->lgrp_childcnt--; 297*0Sstevel@tonic-gate if (changed) 298*0Sstevel@tonic-gate klgrpset_add(*changed, parent->lgrp_id); 299*0Sstevel@tonic-gate count++; 300*0Sstevel@tonic-gate if (parent->lgrp_childcnt != 0) 301*0Sstevel@tonic-gate break; 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate current = parent; 304*0Sstevel@tonic-gate parent = current->lgrp_parent; 305*0Sstevel@tonic-gate lgrpid = current->lgrp_id; 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate #ifdef DEBUG 308*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 309*0Sstevel@tonic-gate prom_printf("lgrp_ancestor_delete: destroy" 310*0Sstevel@tonic-gate " lgrp %d at 0x%p\n", 311*0Sstevel@tonic-gate current->lgrp_id, current); 312*0Sstevel@tonic-gate #endif /* DEBUG */ 313*0Sstevel@tonic-gate lgrp_destroy(current); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate #ifdef DEBUG 317*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 318*0Sstevel@tonic-gate prom_printf("lgrp_ancestor_delete: changed %d lgrps: 0x%llx\n", 319*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 320*0Sstevel@tonic-gate #endif /* DEBUG */ 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate return (count); 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * Consolidate lgrp1 into lgrp2 328*0Sstevel@tonic-gate */ 329*0Sstevel@tonic-gate int 330*0Sstevel@tonic-gate lgrp_consolidate(lgrp_t *lgrp1, lgrp_t *lgrp2, klgrpset_t *changed) 331*0Sstevel@tonic-gate { 332*0Sstevel@tonic-gate klgrpset_t changes; 333*0Sstevel@tonic-gate lgrp_t *child; 334*0Sstevel@tonic-gate int count; 335*0Sstevel@tonic-gate int i; 336*0Sstevel@tonic-gate lgrp_t *parent; 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* 339*0Sstevel@tonic-gate * Leaf lgroups should never need to be consolidated 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate if (lgrp1 == NULL || lgrp2 == NULL || lgrp1->lgrp_childcnt < 1 || 342*0Sstevel@tonic-gate lgrp2->lgrp_childcnt < 1) 343*0Sstevel@tonic-gate return (0); 344*0Sstevel@tonic-gate 345*0Sstevel@tonic-gate #ifdef DEBUG 346*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 347*0Sstevel@tonic-gate prom_printf("lgrp_consolidate(0x%p[%d],0x%p[%d],0x%p)\n", 348*0Sstevel@tonic-gate lgrp1, lgrp1->lgrp_id, lgrp2, lgrp2->lgrp_id, changed); 349*0Sstevel@tonic-gate #endif /* DEBUG */ 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate count = 0; 352*0Sstevel@tonic-gate if (changed) 353*0Sstevel@tonic-gate klgrpset_clear(*changed); 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate /* 356*0Sstevel@tonic-gate * Lgroup represents resources within certain latency, so need to keep 357*0Sstevel@tonic-gate * biggest latency value of lgroups being consolidated 358*0Sstevel@tonic-gate */ 359*0Sstevel@tonic-gate if (lgrp1->lgrp_latency > lgrp2->lgrp_latency) 360*0Sstevel@tonic-gate lgrp2->lgrp_latency = lgrp1->lgrp_latency; 361*0Sstevel@tonic-gate 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * Delete ancestors of lgrp1 that don't have any other children 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate #ifdef DEBUG 366*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 367*0Sstevel@tonic-gate prom_printf("lgrp_consolidate: delete ancestors\n"); 368*0Sstevel@tonic-gate #endif /* DEBUG */ 369*0Sstevel@tonic-gate count += lgrp_ancestor_delete(lgrp1, &changes); 370*0Sstevel@tonic-gate if (changed) { 371*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 372*0Sstevel@tonic-gate klgrpset_or(*changed, lgrp1->lgrp_id); 373*0Sstevel@tonic-gate count++; 374*0Sstevel@tonic-gate } 375*0Sstevel@tonic-gate 376*0Sstevel@tonic-gate /* 377*0Sstevel@tonic-gate * Reparent children lgroups of lgrp1 to lgrp2 378*0Sstevel@tonic-gate */ 379*0Sstevel@tonic-gate for (i = 0; i <= lgrp_alloc_max; i++) { 380*0Sstevel@tonic-gate if (i == lgrp2->lgrp_id || 381*0Sstevel@tonic-gate !klgrpset_ismember(lgrp1->lgrp_children, i)) 382*0Sstevel@tonic-gate continue; 383*0Sstevel@tonic-gate child = lgrp_table[i]; 384*0Sstevel@tonic-gate if (!LGRP_EXISTS(child)) 385*0Sstevel@tonic-gate continue; 386*0Sstevel@tonic-gate #ifdef DEBUG 387*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 388*0Sstevel@tonic-gate prom_printf("lgrp_consolidate: reparent " 389*0Sstevel@tonic-gate "lgrp %d to lgrp %d\n", 390*0Sstevel@tonic-gate child->lgrp_id, lgrp2->lgrp_id); 391*0Sstevel@tonic-gate #endif /* DEBUG */ 392*0Sstevel@tonic-gate klgrpset_or(lgrp2->lgrp_leaves, child->lgrp_leaves); 393*0Sstevel@tonic-gate klgrpset_add(lgrp2->lgrp_children, child->lgrp_id); 394*0Sstevel@tonic-gate lgrp2->lgrp_childcnt++; 395*0Sstevel@tonic-gate child->lgrp_parent = lgrp2; 396*0Sstevel@tonic-gate if (changed) { 397*0Sstevel@tonic-gate klgrpset_add(*changed, child->lgrp_id); 398*0Sstevel@tonic-gate klgrpset_add(*changed, lgrp2->lgrp_id); 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate count += 2; 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate 403*0Sstevel@tonic-gate /* 404*0Sstevel@tonic-gate * Proprogate leaves from lgrp2 to root 405*0Sstevel@tonic-gate */ 406*0Sstevel@tonic-gate child = lgrp2; 407*0Sstevel@tonic-gate parent = child->lgrp_parent; 408*0Sstevel@tonic-gate while (parent != NULL) { 409*0Sstevel@tonic-gate klgrpset_or(parent->lgrp_leaves, child->lgrp_leaves); 410*0Sstevel@tonic-gate if (changed) 411*0Sstevel@tonic-gate klgrpset_add(*changed, parent->lgrp_id); 412*0Sstevel@tonic-gate count++; 413*0Sstevel@tonic-gate child = parent; 414*0Sstevel@tonic-gate parent = parent->lgrp_parent; 415*0Sstevel@tonic-gate } 416*0Sstevel@tonic-gate 417*0Sstevel@tonic-gate #ifdef DEBUG 418*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 419*0Sstevel@tonic-gate prom_printf("lgrp_consolidate: destroy lgrp %d at 0x%p\n", 420*0Sstevel@tonic-gate lgrp1->lgrp_id, lgrp1); 421*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 422*0Sstevel@tonic-gate prom_printf("lgrp_consolidate: changed %d lgrps: 0x%llx\n", 423*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 424*0Sstevel@tonic-gate #endif /* DEBUG */ 425*0Sstevel@tonic-gate 426*0Sstevel@tonic-gate lgrp_destroy(lgrp1); 427*0Sstevel@tonic-gate 428*0Sstevel@tonic-gate return (count); 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate /* 432*0Sstevel@tonic-gate * Collapse duplicates of target lgroups given 433*0Sstevel@tonic-gate */ 434*0Sstevel@tonic-gate int 435*0Sstevel@tonic-gate lgrp_collapse_dups(klgrpset_t target_set, int equidist_only, 436*0Sstevel@tonic-gate klgrpset_t *changed) 437*0Sstevel@tonic-gate { 438*0Sstevel@tonic-gate klgrpset_t changes; 439*0Sstevel@tonic-gate int count; 440*0Sstevel@tonic-gate int i; 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate count = 0; 443*0Sstevel@tonic-gate if (changed) 444*0Sstevel@tonic-gate klgrpset_clear(*changed); 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate if (lgrp_collapse_off) 447*0Sstevel@tonic-gate return (0); 448*0Sstevel@tonic-gate 449*0Sstevel@tonic-gate #ifdef DEBUG 450*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 451*0Sstevel@tonic-gate prom_printf("lgrp_collapse_dups(0x%llx)\n", 452*0Sstevel@tonic-gate (u_longlong_t)target_set); 453*0Sstevel@tonic-gate #endif /* DEBUG */ 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate /* 456*0Sstevel@tonic-gate * Look for duplicates of each target lgroup 457*0Sstevel@tonic-gate */ 458*0Sstevel@tonic-gate for (i = 0; i <= lgrp_alloc_max; i++) { 459*0Sstevel@tonic-gate int j; 460*0Sstevel@tonic-gate lgrp_t *keep; 461*0Sstevel@tonic-gate lgrp_t *target; 462*0Sstevel@tonic-gate 463*0Sstevel@tonic-gate target = lgrp_table[i]; 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * Skip to next lgroup if there isn't one here, this is root 467*0Sstevel@tonic-gate * or leaf lgroup, or this isn't a target lgroup 468*0Sstevel@tonic-gate */ 469*0Sstevel@tonic-gate if (!LGRP_EXISTS(target) || 470*0Sstevel@tonic-gate target == lgrp_root || target->lgrp_childcnt == 0 || 471*0Sstevel@tonic-gate !klgrpset_ismember(target_set, target->lgrp_id)) 472*0Sstevel@tonic-gate continue; 473*0Sstevel@tonic-gate 474*0Sstevel@tonic-gate /* 475*0Sstevel@tonic-gate * Find all lgroups with same resources and latency 476*0Sstevel@tonic-gate */ 477*0Sstevel@tonic-gate #ifdef DEBUG 478*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 479*0Sstevel@tonic-gate prom_printf("lgrp_collapse_dups: find " 480*0Sstevel@tonic-gate "dups of lgrp %d at 0x%p\n", 481*0Sstevel@tonic-gate target->lgrp_id, target); 482*0Sstevel@tonic-gate #endif /* DEBUG */ 483*0Sstevel@tonic-gate keep = NULL; 484*0Sstevel@tonic-gate for (j = 0; j <= lgrp_alloc_max; j++) { 485*0Sstevel@tonic-gate lgrp_t *lgrp; 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate lgrp = lgrp_table[j]; 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate /* 490*0Sstevel@tonic-gate * Skip lgroup if there isn't one here, this is root 491*0Sstevel@tonic-gate * lgroup or leaf (which shouldn't have dups), or this 492*0Sstevel@tonic-gate * lgroup doesn't have same resources 493*0Sstevel@tonic-gate */ 494*0Sstevel@tonic-gate if (!LGRP_EXISTS(lgrp) || 495*0Sstevel@tonic-gate lgrp->lgrp_childcnt == 0 || 496*0Sstevel@tonic-gate !lgrp_rsets_equal(lgrp->lgrp_set, 497*0Sstevel@tonic-gate target->lgrp_set) || 498*0Sstevel@tonic-gate (lgrp->lgrp_latency != target->lgrp_latency && 499*0Sstevel@tonic-gate equidist_only)) 500*0Sstevel@tonic-gate continue; 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate /* 503*0Sstevel@tonic-gate * Keep first matching lgroup (but always keep root) 504*0Sstevel@tonic-gate * and consolidate other duplicates into it 505*0Sstevel@tonic-gate */ 506*0Sstevel@tonic-gate if (keep == NULL) { 507*0Sstevel@tonic-gate keep = lgrp; 508*0Sstevel@tonic-gate #ifdef DEBUG 509*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 510*0Sstevel@tonic-gate prom_printf("lgrp_collapse_dups: " 511*0Sstevel@tonic-gate "keep lgrp %d at 0x%p\n", 512*0Sstevel@tonic-gate keep->lgrp_id, keep); 513*0Sstevel@tonic-gate #endif /* DEBUG */ 514*0Sstevel@tonic-gate } else { 515*0Sstevel@tonic-gate if (lgrp == lgrp_root) { 516*0Sstevel@tonic-gate lgrp = keep; 517*0Sstevel@tonic-gate keep = lgrp_root; 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate #ifdef DEBUG 520*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 521*0Sstevel@tonic-gate prom_printf("lgrp_collapse_dups:" 522*0Sstevel@tonic-gate " consolidate lgrp %d at 0x%p" 523*0Sstevel@tonic-gate " into lgrp %d at 0x%p\n", 524*0Sstevel@tonic-gate lgrp->lgrp_id, lgrp, 525*0Sstevel@tonic-gate keep->lgrp_id, keep); 526*0Sstevel@tonic-gate #endif /* DEBUG */ 527*0Sstevel@tonic-gate count += lgrp_consolidate(lgrp, keep, 528*0Sstevel@tonic-gate &changes); 529*0Sstevel@tonic-gate if (changed) 530*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate } 534*0Sstevel@tonic-gate 535*0Sstevel@tonic-gate #ifdef DEBUG 536*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 537*0Sstevel@tonic-gate prom_printf("lgrp_collapse_dups: changed %d lgrps: 0x%llx\n", 538*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 539*0Sstevel@tonic-gate #endif /* DEBUG */ 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate return (count); 542*0Sstevel@tonic-gate } 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate /* 546*0Sstevel@tonic-gate * Create new parent lgroup with given latency and resources for 547*0Sstevel@tonic-gate * specified child lgroup, and insert it into hierarchy 548*0Sstevel@tonic-gate */ 549*0Sstevel@tonic-gate int 550*0Sstevel@tonic-gate lgrp_new_parent(lgrp_t *child, int latency, klgrpset_t *rset, 551*0Sstevel@tonic-gate klgrpset_t *changed) 552*0Sstevel@tonic-gate { 553*0Sstevel@tonic-gate int count; 554*0Sstevel@tonic-gate lgrp_t *new; 555*0Sstevel@tonic-gate lgrp_t *old; 556*0Sstevel@tonic-gate 557*0Sstevel@tonic-gate count = 0; 558*0Sstevel@tonic-gate if (changed) 559*0Sstevel@tonic-gate klgrpset_clear(*changed); 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate /* 562*0Sstevel@tonic-gate * Create lgroup and set its latency and resources 563*0Sstevel@tonic-gate */ 564*0Sstevel@tonic-gate new = lgrp_create(); 565*0Sstevel@tonic-gate new->lgrp_latency = latency; 566*0Sstevel@tonic-gate lgrp_rsets_add(rset, new->lgrp_set); 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate /* 569*0Sstevel@tonic-gate * Insert new lgroup into hierarchy 570*0Sstevel@tonic-gate */ 571*0Sstevel@tonic-gate old = child->lgrp_parent; 572*0Sstevel@tonic-gate new->lgrp_parent = old; 573*0Sstevel@tonic-gate klgrpset_add(new->lgrp_children, child->lgrp_id); 574*0Sstevel@tonic-gate new->lgrp_childcnt++; 575*0Sstevel@tonic-gate klgrpset_add(new->lgrp_children, child->lgrp_id); 576*0Sstevel@tonic-gate klgrpset_copy(new->lgrp_leaves, child->lgrp_leaves); 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate child->lgrp_parent = new; 579*0Sstevel@tonic-gate if (old) { 580*0Sstevel@tonic-gate klgrpset_del(old->lgrp_children, child->lgrp_id); 581*0Sstevel@tonic-gate klgrpset_add(old->lgrp_children, new->lgrp_id); 582*0Sstevel@tonic-gate if (changed) 583*0Sstevel@tonic-gate klgrpset_add(*changed, old->lgrp_id); 584*0Sstevel@tonic-gate count++; 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate if (changed) { 588*0Sstevel@tonic-gate klgrpset_add(*changed, child->lgrp_id); 589*0Sstevel@tonic-gate klgrpset_add(*changed, new->lgrp_id); 590*0Sstevel@tonic-gate } 591*0Sstevel@tonic-gate count += 2; 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate #ifdef DEBUG 594*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 595*0Sstevel@tonic-gate prom_printf("lgrp_new_parent: changed %d lgrps: 0x%llx\n", 596*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 597*0Sstevel@tonic-gate #endif /* DEBUG */ 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate return (count); 600*0Sstevel@tonic-gate } 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate 603*0Sstevel@tonic-gate /* 604*0Sstevel@tonic-gate * Proprogate resources of new leaf into parent lgroup of given child 605*0Sstevel@tonic-gate */ 606*0Sstevel@tonic-gate int 607*0Sstevel@tonic-gate lgrp_proprogate(lgrp_t *newleaf, lgrp_t *child, int latency, 608*0Sstevel@tonic-gate klgrpset_t *changed) 609*0Sstevel@tonic-gate { 610*0Sstevel@tonic-gate int count; 611*0Sstevel@tonic-gate lgrp_t *parent; 612*0Sstevel@tonic-gate 613*0Sstevel@tonic-gate count = 0; 614*0Sstevel@tonic-gate if (changed) 615*0Sstevel@tonic-gate klgrpset_clear(*changed); 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate if (child == NULL || child->lgrp_parent == NULL) 618*0Sstevel@tonic-gate return (0); 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate parent = child->lgrp_parent; 621*0Sstevel@tonic-gate klgrpset_or(parent->lgrp_leaves, child->lgrp_leaves); 622*0Sstevel@tonic-gate if (changed) 623*0Sstevel@tonic-gate klgrpset_add(*changed, parent->lgrp_id); 624*0Sstevel@tonic-gate count++; 625*0Sstevel@tonic-gate 626*0Sstevel@tonic-gate /* 627*0Sstevel@tonic-gate * Don't proprogate new leaf resources to parent if it already 628*0Sstevel@tonic-gate * contains these resources 629*0Sstevel@tonic-gate */ 630*0Sstevel@tonic-gate if (lgrp_rsets_member_all(parent->lgrp_set, newleaf->lgrp_id)) { 631*0Sstevel@tonic-gate #ifdef DEBUG 632*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 633*0Sstevel@tonic-gate prom_printf("lgrp_proprogate: changed %d lgrps:" 634*0Sstevel@tonic-gate " 0x%llx\n", 635*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 636*0Sstevel@tonic-gate #endif /* DEBUG */ 637*0Sstevel@tonic-gate return (count); 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate /* 641*0Sstevel@tonic-gate * Add leaf resources to parent lgroup 642*0Sstevel@tonic-gate */ 643*0Sstevel@tonic-gate lgrp_rsets_add(newleaf->lgrp_set, parent->lgrp_set); 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate #ifdef DEBUG 646*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) { 647*0Sstevel@tonic-gate prom_printf("lgrp_proprogate: newleaf %d(0x%p), " 648*0Sstevel@tonic-gate "latency %d, child %d(0x%p), parent %d(0x%p)\n", 649*0Sstevel@tonic-gate newleaf->lgrp_id, newleaf, latency, child->lgrp_id, 650*0Sstevel@tonic-gate child, parent->lgrp_id, parent); 651*0Sstevel@tonic-gate prom_printf("lgrp_proprogate: parent's leaves becomes 0x%llx\n", 652*0Sstevel@tonic-gate (u_longlong_t)parent->lgrp_leaves); 653*0Sstevel@tonic-gate } 654*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) { 655*0Sstevel@tonic-gate prom_printf("lgrp_proprogate: adding to parent %d (0x%p)\n", 656*0Sstevel@tonic-gate parent->lgrp_id, parent); 657*0Sstevel@tonic-gate lgrp_rsets_print("parent resources become:", parent->lgrp_set); 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate if (lgrp_topo_debug > 2 && changed) 661*0Sstevel@tonic-gate prom_printf("lgrp_proprogate: changed %d lgrps: 0x%llx\n", 662*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate #endif /* DEBUG */ 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate return (count); 667*0Sstevel@tonic-gate } 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate 670*0Sstevel@tonic-gate /* 671*0Sstevel@tonic-gate * Split parent lgroup of given child if child's leaf decendant (oldleaf) has 672*0Sstevel@tonic-gate * different latency to new leaf lgroup (newleaf) than leaf lgroups of given 673*0Sstevel@tonic-gate * child's siblings 674*0Sstevel@tonic-gate */ 675*0Sstevel@tonic-gate int 676*0Sstevel@tonic-gate lgrp_split(lgrp_t *oldleaf, lgrp_t *newleaf, lgrp_t *child, 677*0Sstevel@tonic-gate klgrpset_t *changed) 678*0Sstevel@tonic-gate { 679*0Sstevel@tonic-gate klgrpset_t changes; 680*0Sstevel@tonic-gate int count; 681*0Sstevel@tonic-gate int i; 682*0Sstevel@tonic-gate int latency; 683*0Sstevel@tonic-gate lgrp_t *parent; 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate count = 0; 686*0Sstevel@tonic-gate if (changed) 687*0Sstevel@tonic-gate klgrpset_clear(*changed); 688*0Sstevel@tonic-gate 689*0Sstevel@tonic-gate if (lgrp_split_off || newleaf == NULL || child == NULL) 690*0Sstevel@tonic-gate return (0); 691*0Sstevel@tonic-gate 692*0Sstevel@tonic-gate /* 693*0Sstevel@tonic-gate * Parent must have more than one child to have a child split from it 694*0Sstevel@tonic-gate * and root lgroup contains all resources and never needs to be split 695*0Sstevel@tonic-gate */ 696*0Sstevel@tonic-gate parent = child->lgrp_parent; 697*0Sstevel@tonic-gate if (parent == NULL || parent->lgrp_childcnt < 2 || parent == lgrp_root) 698*0Sstevel@tonic-gate return (0); 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate #ifdef DEBUG 701*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 702*0Sstevel@tonic-gate prom_printf("lgrp_split(0x%p[%d],0x%p[%d],0x%p[%d],0x%p)\n", 703*0Sstevel@tonic-gate oldleaf, oldleaf->lgrp_id, newleaf, newleaf->lgrp_id, 704*0Sstevel@tonic-gate child, child->lgrp_id, changed); 705*0Sstevel@tonic-gate #endif /* DEBUG */ 706*0Sstevel@tonic-gate 707*0Sstevel@tonic-gate /* 708*0Sstevel@tonic-gate * Get latency between new leaf and old leaf whose lineage it is 709*0Sstevel@tonic-gate * being added 710*0Sstevel@tonic-gate */ 711*0Sstevel@tonic-gate latency = lgrp_plat_latency(oldleaf->lgrp_plathand, 712*0Sstevel@tonic-gate newleaf->lgrp_plathand); 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate /* 715*0Sstevel@tonic-gate * Check whether all sibling leaves of given child lgroup have same 716*0Sstevel@tonic-gate * latency to new leaf 717*0Sstevel@tonic-gate */ 718*0Sstevel@tonic-gate for (i = 0; i <= lgrp_alloc_max; i++) { 719*0Sstevel@tonic-gate lgrp_t *grandparent; 720*0Sstevel@tonic-gate lgrp_t *lgrp; 721*0Sstevel@tonic-gate int sibling_latency; 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate lgrp = lgrp_table[i]; 724*0Sstevel@tonic-gate 725*0Sstevel@tonic-gate /* 726*0Sstevel@tonic-gate * Skip non-existent lgroups, old leaf, and any lgroups that 727*0Sstevel@tonic-gate * don't have parent as common ancestor 728*0Sstevel@tonic-gate */ 729*0Sstevel@tonic-gate if (!LGRP_EXISTS(lgrp) || lgrp == oldleaf || 730*0Sstevel@tonic-gate !klgrpset_ismember(parent->lgrp_leaves, lgrp->lgrp_id)) 731*0Sstevel@tonic-gate continue; 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate /* 734*0Sstevel@tonic-gate * Same latency, so skip 735*0Sstevel@tonic-gate */ 736*0Sstevel@tonic-gate sibling_latency = lgrp_plat_latency(lgrp->lgrp_plathand, 737*0Sstevel@tonic-gate newleaf->lgrp_plathand); 738*0Sstevel@tonic-gate #ifdef DEBUG 739*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 740*0Sstevel@tonic-gate prom_printf("lgrp_split: latency(%d,%d) %d," 741*0Sstevel@tonic-gate " latency(%d,%d) %d\n", 742*0Sstevel@tonic-gate oldleaf->lgrp_id, newleaf->lgrp_id, latency, 743*0Sstevel@tonic-gate lgrp->lgrp_id, newleaf->lgrp_id, sibling_latency); 744*0Sstevel@tonic-gate #endif /* DEBUG */ 745*0Sstevel@tonic-gate if (sibling_latency == latency) 746*0Sstevel@tonic-gate continue; 747*0Sstevel@tonic-gate 748*0Sstevel@tonic-gate /* 749*0Sstevel@tonic-gate * Different latencies, so remove child from its parent and 750*0Sstevel@tonic-gate * make new parent for old leaf with same latency and same 751*0Sstevel@tonic-gate * resources 752*0Sstevel@tonic-gate */ 753*0Sstevel@tonic-gate parent->lgrp_childcnt--; 754*0Sstevel@tonic-gate klgrpset_del(parent->lgrp_children, child->lgrp_id); 755*0Sstevel@tonic-gate klgrpset_del(parent->lgrp_leaves, oldleaf->lgrp_id); 756*0Sstevel@tonic-gate grandparent = parent->lgrp_parent; 757*0Sstevel@tonic-gate if (grandparent) { 758*0Sstevel@tonic-gate grandparent->lgrp_childcnt++; 759*0Sstevel@tonic-gate klgrpset_add(grandparent->lgrp_children, 760*0Sstevel@tonic-gate child->lgrp_id); 761*0Sstevel@tonic-gate count++; 762*0Sstevel@tonic-gate if (changed) 763*0Sstevel@tonic-gate klgrpset_add(*changed, grandparent->lgrp_id); 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate child->lgrp_parent = grandparent; 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate count += lgrp_new_parent(child, parent->lgrp_latency, 768*0Sstevel@tonic-gate parent->lgrp_set, &changes); 769*0Sstevel@tonic-gate if (changed) { 770*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate klgrpset_add(*changed, parent->lgrp_id); 773*0Sstevel@tonic-gate klgrpset_add(*changed, child->lgrp_id); 774*0Sstevel@tonic-gate count += 2; 775*0Sstevel@tonic-gate } 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate parent = child->lgrp_parent; 778*0Sstevel@tonic-gate #ifdef DEBUG 779*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) { 780*0Sstevel@tonic-gate prom_printf("lgrp_split: new parent %d (0x%p) for" 781*0Sstevel@tonic-gate " lgrp %d (0x%p)\n", 782*0Sstevel@tonic-gate parent->lgrp_id, parent, child->lgrp_id, child); 783*0Sstevel@tonic-gate lgrp_rsets_print("new parent resources:", 784*0Sstevel@tonic-gate parent->lgrp_set); 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 788*0Sstevel@tonic-gate prom_printf("lgrp_split: changed %d lgrps: 0x%llx\n", 789*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 790*0Sstevel@tonic-gate #endif /* DEBUG */ 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate return (count); 793*0Sstevel@tonic-gate } 794*0Sstevel@tonic-gate 795*0Sstevel@tonic-gate #ifdef DEBUG 796*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 797*0Sstevel@tonic-gate prom_printf("lgrp_split: no changes\n"); 798*0Sstevel@tonic-gate #endif /* DEBUG */ 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate return (count); 801*0Sstevel@tonic-gate } 802*0Sstevel@tonic-gate 803*0Sstevel@tonic-gate 804*0Sstevel@tonic-gate /* 805*0Sstevel@tonic-gate * Return height of lgroup topology from given lgroup to root 806*0Sstevel@tonic-gate */ 807*0Sstevel@tonic-gate int 808*0Sstevel@tonic-gate lgrp_topo_height(lgrp_t *lgrp) 809*0Sstevel@tonic-gate { 810*0Sstevel@tonic-gate int nlevels; 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate if (!LGRP_EXISTS(lgrp)) 813*0Sstevel@tonic-gate return (0); 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate nlevels = 0; 816*0Sstevel@tonic-gate while (lgrp != NULL) { 817*0Sstevel@tonic-gate lgrp = lgrp->lgrp_parent; 818*0Sstevel@tonic-gate nlevels++; 819*0Sstevel@tonic-gate } 820*0Sstevel@tonic-gate return (nlevels); 821*0Sstevel@tonic-gate } 822*0Sstevel@tonic-gate 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate /* 825*0Sstevel@tonic-gate * Add resources of new leaf to old leaf's lineage 826*0Sstevel@tonic-gate * 827*0Sstevel@tonic-gate * Assumes the following: 828*0Sstevel@tonic-gate * - Lgroup hierarchy consists of at least a root lgroup and its leaves 829*0Sstevel@tonic-gate * including old and new ones given below 830*0Sstevel@tonic-gate * - New leaf lgroup has been created and does not need to have its resources 831*0Sstevel@tonic-gate * added to it 832*0Sstevel@tonic-gate * - Latencies have been set for root and leaf lgroups 833*0Sstevel@tonic-gate */ 834*0Sstevel@tonic-gate int 835*0Sstevel@tonic-gate lgrp_lineage_add(lgrp_t *newleaf, lgrp_t *oldleaf, klgrpset_t *changed) 836*0Sstevel@tonic-gate { 837*0Sstevel@tonic-gate klgrpset_t changes; 838*0Sstevel@tonic-gate lgrp_t *child; 839*0Sstevel@tonic-gate klgrpset_t collapse; 840*0Sstevel@tonic-gate int count; 841*0Sstevel@tonic-gate int latency; 842*0Sstevel@tonic-gate int nlevels; 843*0Sstevel@tonic-gate lgrp_t *parent; 844*0Sstevel@tonic-gate int proprogate; 845*0Sstevel@tonic-gate int total; 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate 848*0Sstevel@tonic-gate count = total = 0; 849*0Sstevel@tonic-gate if (changed) 850*0Sstevel@tonic-gate klgrpset_clear(*changed); 851*0Sstevel@tonic-gate 852*0Sstevel@tonic-gate if (newleaf == NULL || oldleaf == NULL || newleaf == oldleaf) 853*0Sstevel@tonic-gate return (0); 854*0Sstevel@tonic-gate 855*0Sstevel@tonic-gate #ifdef DEBUG 856*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 857*0Sstevel@tonic-gate prom_printf("\nlgrp_lineage_add(0x%p[%d],0x%p[%d],0x%p)\n", 858*0Sstevel@tonic-gate newleaf, newleaf->lgrp_id, oldleaf, oldleaf->lgrp_id, 859*0Sstevel@tonic-gate changed); 860*0Sstevel@tonic-gate #endif /* DEBUG */ 861*0Sstevel@tonic-gate 862*0Sstevel@tonic-gate /* 863*0Sstevel@tonic-gate * Get latency between old and new leaves, so we can determine 864*0Sstevel@tonic-gate * where the new leaf fits in the old leaf's lineage 865*0Sstevel@tonic-gate */ 866*0Sstevel@tonic-gate latency = lgrp_plat_latency(oldleaf->lgrp_plathand, 867*0Sstevel@tonic-gate newleaf->lgrp_plathand); 868*0Sstevel@tonic-gate 869*0Sstevel@tonic-gate /* 870*0Sstevel@tonic-gate * Determine height of lgroup topology from old leaf to root lgroup, 871*0Sstevel@tonic-gate * so height of topology may be limited if necessary 872*0Sstevel@tonic-gate */ 873*0Sstevel@tonic-gate nlevels = lgrp_topo_height(oldleaf); 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate #ifdef DEBUG 876*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 877*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: latency(%d,%d) 0x%x, ht %d\n", 878*0Sstevel@tonic-gate oldleaf->lgrp_id, newleaf->lgrp_id, latency, nlevels); 879*0Sstevel@tonic-gate #endif /* DEBUG */ 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate /* 882*0Sstevel@tonic-gate * Can't add new leaf to old leaf's lineage if we haven't 883*0Sstevel@tonic-gate * determined latency between them yet 884*0Sstevel@tonic-gate */ 885*0Sstevel@tonic-gate if (latency == 0) 886*0Sstevel@tonic-gate return (0); 887*0Sstevel@tonic-gate 888*0Sstevel@tonic-gate child = oldleaf; 889*0Sstevel@tonic-gate parent = child->lgrp_parent; 890*0Sstevel@tonic-gate proprogate = 0; 891*0Sstevel@tonic-gate klgrpset_clear(collapse); 892*0Sstevel@tonic-gate 893*0Sstevel@tonic-gate /* 894*0Sstevel@tonic-gate * Lineage of old leaf is basically a sorted list of the other leaves 895*0Sstevel@tonic-gate * from closest to farthest, so find where to add new leaf to the 896*0Sstevel@tonic-gate * lineage and proprogate its resources from that point up to the root 897*0Sstevel@tonic-gate * lgroup since parent lgroups contain all the resources of their 898*0Sstevel@tonic-gate * children 899*0Sstevel@tonic-gate */ 900*0Sstevel@tonic-gate do { 901*0Sstevel@tonic-gate klgrpset_t rset[LGRP_RSRC_COUNT]; 902*0Sstevel@tonic-gate 903*0Sstevel@tonic-gate #ifdef DEBUG 904*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 905*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: child %d (0x%p), parent" 906*0Sstevel@tonic-gate " %d (0x%p)\n", 907*0Sstevel@tonic-gate child->lgrp_id, child, parent->lgrp_id, parent); 908*0Sstevel@tonic-gate #endif /* DEBUG */ 909*0Sstevel@tonic-gate 910*0Sstevel@tonic-gate /* 911*0Sstevel@tonic-gate * See whether parent lgroup needs to be split 912*0Sstevel@tonic-gate * 913*0Sstevel@tonic-gate * May need to split parent lgroup when it is ancestor to more 914*0Sstevel@tonic-gate * than one leaf, but all its leaves don't have latency to new 915*0Sstevel@tonic-gate * leaf within the parent lgroup's latency 916*0Sstevel@tonic-gate * NOTE: Don't want to collapse this lgroup since we just split 917*0Sstevel@tonic-gate * it from parent 918*0Sstevel@tonic-gate */ 919*0Sstevel@tonic-gate count = lgrp_split(oldleaf, newleaf, child, &changes); 920*0Sstevel@tonic-gate if (count) { 921*0Sstevel@tonic-gate #ifdef DEBUG 922*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 923*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: setting parent" 924*0Sstevel@tonic-gate " for child %d from %d to %d\n", 925*0Sstevel@tonic-gate child->lgrp_id, parent->lgrp_id, 926*0Sstevel@tonic-gate child->lgrp_parent->lgrp_id); 927*0Sstevel@tonic-gate #endif /* DEBUG */ 928*0Sstevel@tonic-gate parent = child->lgrp_parent; 929*0Sstevel@tonic-gate total += count; 930*0Sstevel@tonic-gate if (changed) 931*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 932*0Sstevel@tonic-gate } 933*0Sstevel@tonic-gate 934*0Sstevel@tonic-gate /* 935*0Sstevel@tonic-gate * Already found where resources of new leaf belong in old 936*0Sstevel@tonic-gate * leaf's lineage, so proprogate resources of new leaf up 937*0Sstevel@tonic-gate * through rest of ancestors 938*0Sstevel@tonic-gate */ 939*0Sstevel@tonic-gate if (proprogate) { 940*0Sstevel@tonic-gate total += lgrp_proprogate(newleaf, child, latency, 941*0Sstevel@tonic-gate &changes); 942*0Sstevel@tonic-gate if (changed) 943*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate parent = child->lgrp_parent; 946*0Sstevel@tonic-gate klgrpset_add(collapse, parent->lgrp_id); 947*0Sstevel@tonic-gate child = parent; 948*0Sstevel@tonic-gate parent = parent->lgrp_parent; 949*0Sstevel@tonic-gate continue; 950*0Sstevel@tonic-gate } 951*0Sstevel@tonic-gate 952*0Sstevel@tonic-gate #ifdef DEBUG 953*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 954*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: latency 0x%x," 955*0Sstevel@tonic-gate " parent latency 0x%x\n", 956*0Sstevel@tonic-gate latency, parent->lgrp_latency); 957*0Sstevel@tonic-gate #endif /* DEBUG */ 958*0Sstevel@tonic-gate /* 959*0Sstevel@tonic-gate * As we work our way from the old leaf to the root lgroup, 960*0Sstevel@tonic-gate * new leaf resources should go in between two lgroups or into 961*0Sstevel@tonic-gate * one of the parent lgroups somewhere along the line 962*0Sstevel@tonic-gate */ 963*0Sstevel@tonic-gate if (latency < parent->lgrp_latency) { 964*0Sstevel@tonic-gate lgrp_t *intermed; 965*0Sstevel@tonic-gate 966*0Sstevel@tonic-gate /* 967*0Sstevel@tonic-gate * New leaf resources should go in between current 968*0Sstevel@tonic-gate * child and parent 969*0Sstevel@tonic-gate */ 970*0Sstevel@tonic-gate #ifdef DEBUG 971*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 972*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: " 973*0Sstevel@tonic-gate "latency < parent latency\n"); 974*0Sstevel@tonic-gate #endif /* DEBUG */ 975*0Sstevel@tonic-gate 976*0Sstevel@tonic-gate /* 977*0Sstevel@tonic-gate * Create lgroup with desired resources and insert it 978*0Sstevel@tonic-gate * between child and parent 979*0Sstevel@tonic-gate */ 980*0Sstevel@tonic-gate lgrp_rsets_copy(child->lgrp_set, rset); 981*0Sstevel@tonic-gate lgrp_rsets_add(newleaf->lgrp_set, rset); 982*0Sstevel@tonic-gate if (nlevels >= lgrp_topo_levels) { 983*0Sstevel@tonic-gate if (parent == lgrp_root) 984*0Sstevel@tonic-gate break; 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate #ifdef DEBUG 987*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) { 988*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: " 989*0Sstevel@tonic-gate "replaced parent lgrp %d at 0x%p" 990*0Sstevel@tonic-gate " for lgrp %d\n", 991*0Sstevel@tonic-gate parent->lgrp_id, parent, 992*0Sstevel@tonic-gate child->lgrp_id); 993*0Sstevel@tonic-gate lgrp_rsets_print("old parent" 994*0Sstevel@tonic-gate " resources:", parent->lgrp_set); 995*0Sstevel@tonic-gate lgrp_rsets_print("new parent " 996*0Sstevel@tonic-gate "resources:", rset); 997*0Sstevel@tonic-gate } 998*0Sstevel@tonic-gate #endif /* DEBUG */ 999*0Sstevel@tonic-gate /* 1000*0Sstevel@tonic-gate * Replace contents of parent with new 1001*0Sstevel@tonic-gate * leaf + child resources since new leaf is 1002*0Sstevel@tonic-gate * closer and shift its parent's resources to 1003*0Sstevel@tonic-gate * its parent, etc. until root lgroup reached 1004*0Sstevel@tonic-gate */ 1005*0Sstevel@tonic-gate lgrp_rsets_replace(rset, latency, parent, 1); 1006*0Sstevel@tonic-gate if (*changed) 1007*0Sstevel@tonic-gate klgrpset_or(*changed, parent->lgrp_id); 1008*0Sstevel@tonic-gate total++; 1009*0Sstevel@tonic-gate proprogate++; 1010*0Sstevel@tonic-gate } else { 1011*0Sstevel@tonic-gate total += lgrp_new_parent(child, latency, rset, 1012*0Sstevel@tonic-gate &changes); 1013*0Sstevel@tonic-gate intermed = child->lgrp_parent; 1014*0Sstevel@tonic-gate klgrpset_add(collapse, intermed->lgrp_id); 1015*0Sstevel@tonic-gate if (changed) 1016*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 1017*0Sstevel@tonic-gate child = intermed; 1018*0Sstevel@tonic-gate proprogate++; 1019*0Sstevel@tonic-gate #ifdef DEBUG 1020*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) { 1021*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: new " 1022*0Sstevel@tonic-gate "parent lgrp %d at 0x%p for " 1023*0Sstevel@tonic-gate "lgrp %d\n", intermed->lgrp_id, 1024*0Sstevel@tonic-gate intermed, child->lgrp_id); 1025*0Sstevel@tonic-gate lgrp_rsets_print("new parent " 1026*0Sstevel@tonic-gate "resources:", rset); 1027*0Sstevel@tonic-gate } 1028*0Sstevel@tonic-gate #endif /* DEBUG */ 1029*0Sstevel@tonic-gate continue; 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate } else if (latency == parent->lgrp_latency) { 1033*0Sstevel@tonic-gate /* 1034*0Sstevel@tonic-gate * New leaf resources should go into parent 1035*0Sstevel@tonic-gate */ 1036*0Sstevel@tonic-gate #ifdef DEBUG 1037*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 1038*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: latency == " 1039*0Sstevel@tonic-gate "parent latency\n"); 1040*0Sstevel@tonic-gate #endif /* DEBUG */ 1041*0Sstevel@tonic-gate 1042*0Sstevel@tonic-gate /* 1043*0Sstevel@tonic-gate * It's already there, so don't need to do anything. 1044*0Sstevel@tonic-gate */ 1045*0Sstevel@tonic-gate if (lgrp_rsets_member_all(parent->lgrp_set, 1046*0Sstevel@tonic-gate newleaf->lgrp_id)) 1047*0Sstevel@tonic-gate break; 1048*0Sstevel@tonic-gate 1049*0Sstevel@tonic-gate total += lgrp_proprogate(newleaf, child, latency, 1050*0Sstevel@tonic-gate &changes); 1051*0Sstevel@tonic-gate parent = child->lgrp_parent; 1052*0Sstevel@tonic-gate klgrpset_add(collapse, parent->lgrp_id); 1053*0Sstevel@tonic-gate if (changed) 1054*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 1055*0Sstevel@tonic-gate 1056*0Sstevel@tonic-gate proprogate++; 1057*0Sstevel@tonic-gate } 1058*0Sstevel@tonic-gate 1059*0Sstevel@tonic-gate child = parent; 1060*0Sstevel@tonic-gate parent = parent->lgrp_parent; 1061*0Sstevel@tonic-gate } while (parent != NULL); 1062*0Sstevel@tonic-gate 1063*0Sstevel@tonic-gate /* 1064*0Sstevel@tonic-gate * Consolidate any duplicate lgroups of ones just changed 1065*0Sstevel@tonic-gate * Assume that there were no duplicates before last round of changes 1066*0Sstevel@tonic-gate */ 1067*0Sstevel@tonic-gate #ifdef DEBUG 1068*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 1069*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: collapsing dups....\n"); 1070*0Sstevel@tonic-gate #endif /* DEBUG */ 1071*0Sstevel@tonic-gate 1072*0Sstevel@tonic-gate total += lgrp_collapse_dups(collapse, lgrp_collapse_equidist, 1073*0Sstevel@tonic-gate &changes); 1074*0Sstevel@tonic-gate if (changed) 1075*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate #ifdef DEBUG 1078*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 1079*0Sstevel@tonic-gate prom_printf("lgrp_lineage_add: changed %d lgrps: 0x%llx\n", 1080*0Sstevel@tonic-gate total, (u_longlong_t)*changed); 1081*0Sstevel@tonic-gate #endif /* DEBUG */ 1082*0Sstevel@tonic-gate 1083*0Sstevel@tonic-gate return (total); 1084*0Sstevel@tonic-gate } 1085*0Sstevel@tonic-gate 1086*0Sstevel@tonic-gate 1087*0Sstevel@tonic-gate /* 1088*0Sstevel@tonic-gate * Add leaf lgroup to lgroup topology 1089*0Sstevel@tonic-gate */ 1090*0Sstevel@tonic-gate int 1091*0Sstevel@tonic-gate lgrp_leaf_add(lgrp_t *leaf, lgrp_t **lgrps, int lgrp_count, 1092*0Sstevel@tonic-gate klgrpset_t *changed) 1093*0Sstevel@tonic-gate { 1094*0Sstevel@tonic-gate klgrpset_t changes; 1095*0Sstevel@tonic-gate int count; 1096*0Sstevel@tonic-gate int i; 1097*0Sstevel@tonic-gate int latency; 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 || 1100*0Sstevel@tonic-gate !lgrp_initialized); 1101*0Sstevel@tonic-gate 1102*0Sstevel@tonic-gate #ifdef DEBUG 1103*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 1104*0Sstevel@tonic-gate prom_printf("\nlgrp_leaf_add(0x%p[%d],0x%p,%d,0x%p)\n", 1105*0Sstevel@tonic-gate leaf, leaf->lgrp_id, lgrps, lgrp_count, changed); 1106*0Sstevel@tonic-gate #endif /* DEBUG */ 1107*0Sstevel@tonic-gate 1108*0Sstevel@tonic-gate count = 0; 1109*0Sstevel@tonic-gate if (changed) 1110*0Sstevel@tonic-gate klgrpset_clear(*changed); 1111*0Sstevel@tonic-gate 1112*0Sstevel@tonic-gate /* 1113*0Sstevel@tonic-gate * Initialize parent of leaf lgroup to root 1114*0Sstevel@tonic-gate */ 1115*0Sstevel@tonic-gate if (leaf->lgrp_parent == NULL) { 1116*0Sstevel@tonic-gate leaf->lgrp_parent = lgrp_root; 1117*0Sstevel@tonic-gate lgrp_root->lgrp_childcnt++; 1118*0Sstevel@tonic-gate klgrpset_add(lgrp_root->lgrp_children, leaf->lgrp_id); 1119*0Sstevel@tonic-gate 1120*0Sstevel@tonic-gate klgrpset_or(lgrp_root->lgrp_leaves, leaf->lgrp_leaves); 1121*0Sstevel@tonic-gate lgrp_rsets_add(leaf->lgrp_set, lgrp_root->lgrp_set); 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate #ifdef DEBUG 1124*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 1125*0Sstevel@tonic-gate lgrp_rsets_print("lgrp_leaf_add: root lgrp resources", 1126*0Sstevel@tonic-gate lgrp_root->lgrp_set); 1127*0Sstevel@tonic-gate #endif /* DEBUG */ 1128*0Sstevel@tonic-gate 1129*0Sstevel@tonic-gate if (changed) { 1130*0Sstevel@tonic-gate klgrpset_add(*changed, lgrp_root->lgrp_id); 1131*0Sstevel@tonic-gate klgrpset_add(*changed, leaf->lgrp_id); 1132*0Sstevel@tonic-gate } 1133*0Sstevel@tonic-gate count += 2; 1134*0Sstevel@tonic-gate } 1135*0Sstevel@tonic-gate 1136*0Sstevel@tonic-gate /* 1137*0Sstevel@tonic-gate * Can't add leaf lgroup to rest of topology (and vice versa) unless 1138*0Sstevel@tonic-gate * latency for it is available 1139*0Sstevel@tonic-gate */ 1140*0Sstevel@tonic-gate latency = lgrp_plat_latency(leaf->lgrp_plathand, leaf->lgrp_plathand); 1141*0Sstevel@tonic-gate if (latency == 0) { 1142*0Sstevel@tonic-gate #ifdef DEBUG 1143*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 1144*0Sstevel@tonic-gate prom_printf("lgrp_leaf_add: changed %d lgrps: 0x%llx\n", 1145*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 1146*0Sstevel@tonic-gate #endif /* DEBUG */ 1147*0Sstevel@tonic-gate return (count); 1148*0Sstevel@tonic-gate } 1149*0Sstevel@tonic-gate 1150*0Sstevel@tonic-gate /* 1151*0Sstevel@tonic-gate * Make sure that root and leaf lgroup latencies are set 1152*0Sstevel@tonic-gate */ 1153*0Sstevel@tonic-gate lgrp_root->lgrp_latency = lgrp_plat_latency(lgrp_root->lgrp_plathand, 1154*0Sstevel@tonic-gate lgrp_root->lgrp_plathand); 1155*0Sstevel@tonic-gate leaf->lgrp_latency = latency; 1156*0Sstevel@tonic-gate 1157*0Sstevel@tonic-gate /* 1158*0Sstevel@tonic-gate * Add leaf to lineage of other leaves and vice versa 1159*0Sstevel@tonic-gate * since leaves come into existence at different times 1160*0Sstevel@tonic-gate */ 1161*0Sstevel@tonic-gate for (i = 0; i < lgrp_count; i++) { 1162*0Sstevel@tonic-gate lgrp_t *lgrp; 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate lgrp = lgrps[i]; 1165*0Sstevel@tonic-gate 1166*0Sstevel@tonic-gate /* 1167*0Sstevel@tonic-gate * Skip non-existent lgroups, new leaf lgroup, and 1168*0Sstevel@tonic-gate * non-leaf lgroups 1169*0Sstevel@tonic-gate */ 1170*0Sstevel@tonic-gate if (!LGRP_EXISTS(lgrp) || lgrp == leaf || 1171*0Sstevel@tonic-gate lgrp->lgrp_childcnt != 0) { 1172*0Sstevel@tonic-gate #ifdef DEBUG 1173*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 1174*0Sstevel@tonic-gate prom_printf("lgrp_leaf_add: skip " 1175*0Sstevel@tonic-gate "lgrp %d at 0x%p\n", 1176*0Sstevel@tonic-gate lgrp->lgrp_id, lgrp); 1177*0Sstevel@tonic-gate #endif /* DEBUG */ 1178*0Sstevel@tonic-gate continue; 1179*0Sstevel@tonic-gate } 1180*0Sstevel@tonic-gate 1181*0Sstevel@tonic-gate #ifdef DEBUG 1182*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 1183*0Sstevel@tonic-gate prom_printf("lgrp_leaf_add: lgrp %d (0x%p) =>" 1184*0Sstevel@tonic-gate " lgrp %d (0x%p)\n", 1185*0Sstevel@tonic-gate leaf->lgrp_id, leaf, lgrp->lgrp_id, lgrp); 1186*0Sstevel@tonic-gate #endif /* DEBUG */ 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate count += lgrp_lineage_add(leaf, lgrp, &changes); 1189*0Sstevel@tonic-gate if (changed) 1190*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 1191*0Sstevel@tonic-gate 1192*0Sstevel@tonic-gate count += lgrp_lineage_add(lgrp, leaf, &changes); 1193*0Sstevel@tonic-gate if (changed) 1194*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 1195*0Sstevel@tonic-gate } 1196*0Sstevel@tonic-gate 1197*0Sstevel@tonic-gate #ifdef DEBUG 1198*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 1199*0Sstevel@tonic-gate prom_printf("lgrp_leaf_add: changed %d lgrps: 0x%llx\n", 1200*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 1201*0Sstevel@tonic-gate #endif /* DEBUG */ 1202*0Sstevel@tonic-gate 1203*0Sstevel@tonic-gate return (count); 1204*0Sstevel@tonic-gate } 1205*0Sstevel@tonic-gate 1206*0Sstevel@tonic-gate 1207*0Sstevel@tonic-gate /* 1208*0Sstevel@tonic-gate * Remove resources of leaf from lgroup hierarchy 1209*0Sstevel@tonic-gate */ 1210*0Sstevel@tonic-gate int 1211*0Sstevel@tonic-gate lgrp_leaf_delete(lgrp_t *leaf, lgrp_t **lgrps, int lgrp_count, 1212*0Sstevel@tonic-gate klgrpset_t *changed) 1213*0Sstevel@tonic-gate { 1214*0Sstevel@tonic-gate klgrpset_t changes; 1215*0Sstevel@tonic-gate klgrpset_t collapse; 1216*0Sstevel@tonic-gate int count; 1217*0Sstevel@tonic-gate int i; 1218*0Sstevel@tonic-gate lgrp_t *lgrp; 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&cpu_lock) || curthread->t_preempt > 0 || 1221*0Sstevel@tonic-gate !lgrp_initialized); 1222*0Sstevel@tonic-gate 1223*0Sstevel@tonic-gate count = 0; 1224*0Sstevel@tonic-gate klgrpset_clear(collapse); 1225*0Sstevel@tonic-gate if (changed) 1226*0Sstevel@tonic-gate klgrpset_clear(*changed); 1227*0Sstevel@tonic-gate 1228*0Sstevel@tonic-gate /* 1229*0Sstevel@tonic-gate * Nothing to do if no leaf given 1230*0Sstevel@tonic-gate */ 1231*0Sstevel@tonic-gate if (leaf == NULL) 1232*0Sstevel@tonic-gate return (0); 1233*0Sstevel@tonic-gate 1234*0Sstevel@tonic-gate #ifdef DEBUG 1235*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 1236*0Sstevel@tonic-gate prom_printf("lgrp_leaf_delete(0x%p[%d],0x%p,%d,0x%p)\n", 1237*0Sstevel@tonic-gate leaf, leaf->lgrp_id, lgrps, lgrp_count, changed); 1238*0Sstevel@tonic-gate #endif /* DEBUG */ 1239*0Sstevel@tonic-gate 1240*0Sstevel@tonic-gate /* 1241*0Sstevel@tonic-gate * Remove leaf from any lgroups containing its resources 1242*0Sstevel@tonic-gate */ 1243*0Sstevel@tonic-gate for (i = 0; i < lgrp_count; i++) { 1244*0Sstevel@tonic-gate lgrp = lgrps[i]; 1245*0Sstevel@tonic-gate if (lgrp == NULL || lgrp->lgrp_id == LGRP_NONE || 1246*0Sstevel@tonic-gate !lgrp_rsets_member(lgrp->lgrp_set, leaf->lgrp_id)) 1247*0Sstevel@tonic-gate continue; 1248*0Sstevel@tonic-gate 1249*0Sstevel@tonic-gate #ifdef DEBUG 1250*0Sstevel@tonic-gate if (lgrp_topo_debug > 0) 1251*0Sstevel@tonic-gate prom_printf("lgrp_leaf_delete: remove leaf from" 1252*0Sstevel@tonic-gate " lgrp %d at %p\n", lgrp->lgrp_id, lgrp); 1253*0Sstevel@tonic-gate #endif /* DEBUG */ 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate lgrp_rsets_delete(lgrp, leaf->lgrp_id, 0); 1256*0Sstevel@tonic-gate klgrpset_del(lgrp->lgrp_leaves, leaf->lgrp_id); 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate klgrpset_add(collapse, lgrp->lgrp_id); 1259*0Sstevel@tonic-gate count++; 1260*0Sstevel@tonic-gate } 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate /* 1263*0Sstevel@tonic-gate * Remove leaf and its ancestors that don't have any other children 1264*0Sstevel@tonic-gate */ 1265*0Sstevel@tonic-gate #ifdef DEBUG 1266*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 1267*0Sstevel@tonic-gate prom_printf("lgrp_leaf_delete: remove leaf and ancestors\n"); 1268*0Sstevel@tonic-gate #endif /* DEBUG */ 1269*0Sstevel@tonic-gate 1270*0Sstevel@tonic-gate count += lgrp_ancestor_delete(leaf, &changes); 1271*0Sstevel@tonic-gate klgrpset_or(collapse, changes); 1272*0Sstevel@tonic-gate klgrpset_add(collapse, leaf->lgrp_id); 1273*0Sstevel@tonic-gate count++; 1274*0Sstevel@tonic-gate lgrp_destroy(leaf); 1275*0Sstevel@tonic-gate 1276*0Sstevel@tonic-gate /* 1277*0Sstevel@tonic-gate * Consolidate any duplicate lgroups of ones just changed 1278*0Sstevel@tonic-gate * Assume that there were no duplicates before last round of changes 1279*0Sstevel@tonic-gate */ 1280*0Sstevel@tonic-gate #ifdef DEBUG 1281*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) 1282*0Sstevel@tonic-gate prom_printf("lgrp_leaf_delete: collapsing dups\n"); 1283*0Sstevel@tonic-gate #endif /* DEBUG */ 1284*0Sstevel@tonic-gate count += lgrp_collapse_dups(collapse, lgrp_collapse_equidist, 1285*0Sstevel@tonic-gate &changes); 1286*0Sstevel@tonic-gate klgrpset_or(collapse, changes); 1287*0Sstevel@tonic-gate if (changed) 1288*0Sstevel@tonic-gate klgrpset_copy(*changed, collapse); 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate #ifdef DEBUG 1291*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 1292*0Sstevel@tonic-gate prom_printf("lgrp_leaf_delete: changed %d lgrps: 0x%llx\n", 1293*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 1294*0Sstevel@tonic-gate #endif /* DEBUG */ 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate return (count); 1297*0Sstevel@tonic-gate } 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate /* 1301*0Sstevel@tonic-gate * Flatten lgroup topology down to height specified 1302*0Sstevel@tonic-gate */ 1303*0Sstevel@tonic-gate int 1304*0Sstevel@tonic-gate lgrp_topo_flatten(int levels, lgrp_t **lgrps, int lgrp_count, 1305*0Sstevel@tonic-gate klgrpset_t *changed) 1306*0Sstevel@tonic-gate { 1307*0Sstevel@tonic-gate int count; 1308*0Sstevel@tonic-gate int i; 1309*0Sstevel@tonic-gate lgrp_t *lgrp; 1310*0Sstevel@tonic-gate 1311*0Sstevel@tonic-gate /* 1312*0Sstevel@tonic-gate * Only flatten down to 2 level for now 1313*0Sstevel@tonic-gate */ 1314*0Sstevel@tonic-gate if (levels != 2) 1315*0Sstevel@tonic-gate return (0); 1316*0Sstevel@tonic-gate 1317*0Sstevel@tonic-gate /* 1318*0Sstevel@tonic-gate * Look for non-leaf lgroups to remove and leaf lgroups to reparent 1319*0Sstevel@tonic-gate */ 1320*0Sstevel@tonic-gate count = 0; 1321*0Sstevel@tonic-gate for (i = 0; i <= lgrp_count; i++) { 1322*0Sstevel@tonic-gate /* 1323*0Sstevel@tonic-gate * Skip non-existent lgroups and root 1324*0Sstevel@tonic-gate */ 1325*0Sstevel@tonic-gate lgrp = lgrps[i]; 1326*0Sstevel@tonic-gate if (!LGRP_EXISTS(lgrp) || lgrp == lgrp_root) 1327*0Sstevel@tonic-gate continue; 1328*0Sstevel@tonic-gate 1329*0Sstevel@tonic-gate if (lgrp->lgrp_childcnt > 0) { 1330*0Sstevel@tonic-gate lgrp_t *parent; 1331*0Sstevel@tonic-gate 1332*0Sstevel@tonic-gate /* 1333*0Sstevel@tonic-gate * Remove non-leaf lgroup from lgroup topology 1334*0Sstevel@tonic-gate */ 1335*0Sstevel@tonic-gate parent = lgrp->lgrp_parent; 1336*0Sstevel@tonic-gate if (changed) { 1337*0Sstevel@tonic-gate klgrpset_add(*changed, lgrp->lgrp_id); 1338*0Sstevel@tonic-gate klgrpset_add(*changed, parent->lgrp_id); 1339*0Sstevel@tonic-gate count += 2; 1340*0Sstevel@tonic-gate } 1341*0Sstevel@tonic-gate if (parent) { 1342*0Sstevel@tonic-gate klgrpset_del(parent->lgrp_children, 1343*0Sstevel@tonic-gate lgrp->lgrp_id); 1344*0Sstevel@tonic-gate parent->lgrp_childcnt--; 1345*0Sstevel@tonic-gate } 1346*0Sstevel@tonic-gate lgrp_destroy(lgrp); 1347*0Sstevel@tonic-gate } else if (lgrp->lgrp_parent != lgrp_root) { 1348*0Sstevel@tonic-gate /* 1349*0Sstevel@tonic-gate * Reparent leaf lgroup to root 1350*0Sstevel@tonic-gate */ 1351*0Sstevel@tonic-gate if (changed) { 1352*0Sstevel@tonic-gate klgrpset_add(*changed, lgrp_root->lgrp_id); 1353*0Sstevel@tonic-gate klgrpset_add(*changed, lgrp->lgrp_id); 1354*0Sstevel@tonic-gate count += 2; 1355*0Sstevel@tonic-gate } 1356*0Sstevel@tonic-gate lgrp->lgrp_parent = lgrp_root; 1357*0Sstevel@tonic-gate klgrpset_add(lgrp_root->lgrp_children, lgrp->lgrp_id); 1358*0Sstevel@tonic-gate lgrp_root->lgrp_childcnt++; 1359*0Sstevel@tonic-gate klgrpset_add(lgrp_root->lgrp_leaves, lgrp->lgrp_id); 1360*0Sstevel@tonic-gate } 1361*0Sstevel@tonic-gate } 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate return (count); 1364*0Sstevel@tonic-gate } 1365*0Sstevel@tonic-gate 1366*0Sstevel@tonic-gate 1367*0Sstevel@tonic-gate /* 1368*0Sstevel@tonic-gate * Return current height limit for lgroup topology 1369*0Sstevel@tonic-gate */ 1370*0Sstevel@tonic-gate int 1371*0Sstevel@tonic-gate lgrp_topo_ht_limit(void) 1372*0Sstevel@tonic-gate { 1373*0Sstevel@tonic-gate return (lgrp_topo_levels); 1374*0Sstevel@tonic-gate } 1375*0Sstevel@tonic-gate 1376*0Sstevel@tonic-gate 1377*0Sstevel@tonic-gate /* 1378*0Sstevel@tonic-gate * Return default height limit for lgroup topology 1379*0Sstevel@tonic-gate */ 1380*0Sstevel@tonic-gate int 1381*0Sstevel@tonic-gate lgrp_topo_ht_limit_default(void) 1382*0Sstevel@tonic-gate { 1383*0Sstevel@tonic-gate return (LGRP_TOPO_LEVELS); 1384*0Sstevel@tonic-gate } 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate 1387*0Sstevel@tonic-gate /* 1388*0Sstevel@tonic-gate * Set height limit for lgroup topology 1389*0Sstevel@tonic-gate */ 1390*0Sstevel@tonic-gate int 1391*0Sstevel@tonic-gate lgrp_topo_ht_limit_set(int ht) 1392*0Sstevel@tonic-gate { 1393*0Sstevel@tonic-gate if (ht > LGRP_TOPO_LEVELS_MAX) 1394*0Sstevel@tonic-gate lgrp_topo_levels = LGRP_TOPO_LEVELS_MAX; 1395*0Sstevel@tonic-gate else 1396*0Sstevel@tonic-gate lgrp_topo_levels = ht; 1397*0Sstevel@tonic-gate 1398*0Sstevel@tonic-gate return (ht); 1399*0Sstevel@tonic-gate } 1400*0Sstevel@tonic-gate 1401*0Sstevel@tonic-gate 1402*0Sstevel@tonic-gate /* 1403*0Sstevel@tonic-gate * Update lgroup topology for any leaves that don't have their latency set 1404*0Sstevel@tonic-gate * 1405*0Sstevel@tonic-gate * This may happen on some machines when the lgroup platform support doesn't 1406*0Sstevel@tonic-gate * know the latencies between nodes soon enough to provide it when the 1407*0Sstevel@tonic-gate * resources are being added. If the lgroup platform code needs to probe 1408*0Sstevel@tonic-gate * memory to determine the latencies between nodes, it must wait until the 1409*0Sstevel@tonic-gate * CPUs become active so at least one CPU in each node can probe memory in 1410*0Sstevel@tonic-gate * each node. 1411*0Sstevel@tonic-gate */ 1412*0Sstevel@tonic-gate int 1413*0Sstevel@tonic-gate lgrp_topo_update(lgrp_t **lgrps, int lgrp_count, klgrpset_t *changed) 1414*0Sstevel@tonic-gate { 1415*0Sstevel@tonic-gate klgrpset_t changes; 1416*0Sstevel@tonic-gate int count; 1417*0Sstevel@tonic-gate int i; 1418*0Sstevel@tonic-gate lgrp_t *lgrp; 1419*0Sstevel@tonic-gate 1420*0Sstevel@tonic-gate count = 0; 1421*0Sstevel@tonic-gate if (changed) 1422*0Sstevel@tonic-gate klgrpset_clear(*changed); 1423*0Sstevel@tonic-gate 1424*0Sstevel@tonic-gate /* 1425*0Sstevel@tonic-gate * For UMA machines, make sure that root lgroup contains all 1426*0Sstevel@tonic-gate * resources. The root lgrp should also name itself as its own leaf 1427*0Sstevel@tonic-gate */ 1428*0Sstevel@tonic-gate if (nlgrps == 1) { 1429*0Sstevel@tonic-gate for (i = 0; i < LGRP_RSRC_COUNT; i++) 1430*0Sstevel@tonic-gate klgrpset_add(lgrp_root->lgrp_set[i], 1431*0Sstevel@tonic-gate lgrp_root->lgrp_id); 1432*0Sstevel@tonic-gate klgrpset_add(lgrp_root->lgrp_leaves, lgrp_root->lgrp_id); 1433*0Sstevel@tonic-gate return (0); 1434*0Sstevel@tonic-gate } 1435*0Sstevel@tonic-gate 1436*0Sstevel@tonic-gate mutex_enter(&cpu_lock); 1437*0Sstevel@tonic-gate pause_cpus(NULL); 1438*0Sstevel@tonic-gate 1439*0Sstevel@tonic-gate /* 1440*0Sstevel@tonic-gate * Look for any leaf lgroup without its latency set, finish adding it 1441*0Sstevel@tonic-gate * to the lgroup topology assuming that it exists and has the root 1442*0Sstevel@tonic-gate * lgroup as its parent, and update the memory nodes of all lgroups 1443*0Sstevel@tonic-gate * that have it as a memory resource. 1444*0Sstevel@tonic-gate */ 1445*0Sstevel@tonic-gate for (i = 0; i < lgrp_count; i++) { 1446*0Sstevel@tonic-gate lgrp = lgrps[i]; 1447*0Sstevel@tonic-gate 1448*0Sstevel@tonic-gate /* 1449*0Sstevel@tonic-gate * Skip non-existent and non-leaf lgroups and any lgroup 1450*0Sstevel@tonic-gate * with its latency set already 1451*0Sstevel@tonic-gate */ 1452*0Sstevel@tonic-gate if (lgrp == NULL || lgrp->lgrp_id == LGRP_NONE || 1453*0Sstevel@tonic-gate lgrp->lgrp_childcnt != 0 || lgrp->lgrp_latency != 0) 1454*0Sstevel@tonic-gate continue; 1455*0Sstevel@tonic-gate 1456*0Sstevel@tonic-gate #ifdef DEBUG 1457*0Sstevel@tonic-gate if (lgrp_topo_debug > 1) { 1458*0Sstevel@tonic-gate prom_printf("\nlgrp_topo_update: updating lineage " 1459*0Sstevel@tonic-gate "of lgrp %d at 0x%p\n", lgrp->lgrp_id, lgrp); 1460*0Sstevel@tonic-gate } 1461*0Sstevel@tonic-gate #endif /* DEBUG */ 1462*0Sstevel@tonic-gate 1463*0Sstevel@tonic-gate count += lgrp_leaf_add(lgrp, lgrps, lgrp_count, &changes); 1464*0Sstevel@tonic-gate if (changed) 1465*0Sstevel@tonic-gate klgrpset_or(*changed, changes); 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gate if (!klgrpset_isempty(changes)) 1468*0Sstevel@tonic-gate (void) lgrp_mnode_update(changes, NULL); 1469*0Sstevel@tonic-gate 1470*0Sstevel@tonic-gate #ifdef DEBUG 1471*0Sstevel@tonic-gate if (lgrp_topo_debug > 1 && changed) 1472*0Sstevel@tonic-gate prom_printf("lgrp_topo_update: changed %d lgrps: " 1473*0Sstevel@tonic-gate "0x%llx\n", 1474*0Sstevel@tonic-gate count, (u_longlong_t)*changed); 1475*0Sstevel@tonic-gate #endif /* DEBUG */ 1476*0Sstevel@tonic-gate } 1477*0Sstevel@tonic-gate 1478*0Sstevel@tonic-gate if (lgrp_topo_levels < LGRP_TOPO_LEVELS && lgrp_topo_levels == 2) { 1479*0Sstevel@tonic-gate count += lgrp_topo_flatten(2, lgrps, lgrp_count, changed); 1480*0Sstevel@tonic-gate (void) lpl_topo_flatten(2); 1481*0Sstevel@tonic-gate } 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate start_cpus(); 1484*0Sstevel@tonic-gate mutex_exit(&cpu_lock); 1485*0Sstevel@tonic-gate 1486*0Sstevel@tonic-gate return (count); 1487*0Sstevel@tonic-gate } 1488*0Sstevel@tonic-gate 1489*0Sstevel@tonic-gate #ifdef DEBUG 1490*0Sstevel@tonic-gate void 1491*0Sstevel@tonic-gate lgrp_print(lgrp_t *lgrp) 1492*0Sstevel@tonic-gate { 1493*0Sstevel@tonic-gate lgrp_t *parent; 1494*0Sstevel@tonic-gate 1495*0Sstevel@tonic-gate prom_printf("LGRP %d", lgrp->lgrp_id); 1496*0Sstevel@tonic-gate if (lgrp->lgrp_childcnt == 0) 1497*0Sstevel@tonic-gate prom_printf(" (plathand %p)\n", 1498*0Sstevel@tonic-gate (void *)lgrp->lgrp_plathand); 1499*0Sstevel@tonic-gate else 1500*0Sstevel@tonic-gate prom_printf("\n"); 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate prom_printf("\tlatency %d\n", lgrp->lgrp_latency); 1503*0Sstevel@tonic-gate 1504*0Sstevel@tonic-gate lgrp_rsets_print("\tresources", lgrp->lgrp_set); 1505*0Sstevel@tonic-gate 1506*0Sstevel@tonic-gate parent = lgrp->lgrp_parent; 1507*0Sstevel@tonic-gate prom_printf("\tparent 0x%p", parent); 1508*0Sstevel@tonic-gate if (parent) 1509*0Sstevel@tonic-gate prom_printf("[%d]\n", parent->lgrp_id); 1510*0Sstevel@tonic-gate else 1511*0Sstevel@tonic-gate prom_printf("\n"); 1512*0Sstevel@tonic-gate 1513*0Sstevel@tonic-gate prom_printf("\tchild count %d, children ", lgrp->lgrp_childcnt); 1514*0Sstevel@tonic-gate klgrpset_print(lgrp->lgrp_children); 1515*0Sstevel@tonic-gate 1516*0Sstevel@tonic-gate prom_printf("\tleaves "); 1517*0Sstevel@tonic-gate klgrpset_print(lgrp->lgrp_leaves); 1518*0Sstevel@tonic-gate } 1519*0Sstevel@tonic-gate 1520*0Sstevel@tonic-gate 1521*0Sstevel@tonic-gate void 1522*0Sstevel@tonic-gate lgrp_topo_print(lgrp_t **lgrps, int lgrp_max) 1523*0Sstevel@tonic-gate { 1524*0Sstevel@tonic-gate klgrpset_t siblings; 1525*0Sstevel@tonic-gate 1526*0Sstevel@tonic-gate lgrp_print(lgrp_root); 1527*0Sstevel@tonic-gate siblings = lgrp_root->lgrp_children; 1528*0Sstevel@tonic-gate while (!klgrpset_isempty(siblings)) { 1529*0Sstevel@tonic-gate klgrpset_t children; 1530*0Sstevel@tonic-gate int i; 1531*0Sstevel@tonic-gate 1532*0Sstevel@tonic-gate klgrpset_clear(children); 1533*0Sstevel@tonic-gate for (i = 0; i <= lgrp_max; i++) { 1534*0Sstevel@tonic-gate lgrp_t *lgrp; 1535*0Sstevel@tonic-gate 1536*0Sstevel@tonic-gate lgrp = lgrps[i]; 1537*0Sstevel@tonic-gate if (lgrp == NULL || !klgrpset_ismember(siblings, i)) 1538*0Sstevel@tonic-gate continue; 1539*0Sstevel@tonic-gate lgrp_print(lgrp); 1540*0Sstevel@tonic-gate klgrpset_or(children, lgrp->lgrp_children); 1541*0Sstevel@tonic-gate } 1542*0Sstevel@tonic-gate klgrpset_copy(siblings, children); 1543*0Sstevel@tonic-gate } 1544*0Sstevel@tonic-gate } 1545*0Sstevel@tonic-gate #endif /* DEBUG */ 1546