1*7aec1d6eScindi /* 2*7aec1d6eScindi * CDDL HEADER START 3*7aec1d6eScindi * 4*7aec1d6eScindi * The contents of this file are subject to the terms of the 5*7aec1d6eScindi * Common Development and Distribution License, Version 1.0 only 6*7aec1d6eScindi * (the "License"). You may not use this file except in compliance 7*7aec1d6eScindi * with the License. 8*7aec1d6eScindi * 9*7aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7aec1d6eScindi * or http://www.opensolaris.org/os/licensing. 11*7aec1d6eScindi * See the License for the specific language governing permissions 12*7aec1d6eScindi * and limitations under the License. 13*7aec1d6eScindi * 14*7aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each 15*7aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the 17*7aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying 18*7aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner] 19*7aec1d6eScindi * 20*7aec1d6eScindi * CDDL HEADER END 21*7aec1d6eScindi */ 22*7aec1d6eScindi /* 23*7aec1d6eScindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*7aec1d6eScindi * Use is subject to license terms. 25*7aec1d6eScindi */ 26*7aec1d6eScindi 27*7aec1d6eScindi #pragma ident "%Z%%M% %I% %E% SMI" 28*7aec1d6eScindi 29*7aec1d6eScindi /* 30*7aec1d6eScindi * Topology Nodes 31*7aec1d6eScindi * 32*7aec1d6eScindi * Topology nodes, tnode_t, are data structures containing per-FMRI 33*7aec1d6eScindi * information and are linked together to form the topology tree. 34*7aec1d6eScindi * Nodes are created during the enumeration process of topo_snap_hold() 35*7aec1d6eScindi * and destroyed during topo_snap_rele(). For the most part, tnode_t data 36*7aec1d6eScindi * is read-only and no lock protection is required. Nodes are 37*7aec1d6eScindi * held in place during tree walk functions. Tree walk functions 38*7aec1d6eScindi * may access node data safely without locks. The exception to this rule 39*7aec1d6eScindi * is data associated with node properties (topo_prop.c). Properties 40*7aec1d6eScindi * may change at anytime and are protected by a per-property locking 41*7aec1d6eScindi * strategy. 42*7aec1d6eScindi * 43*7aec1d6eScindi * Enumerator plugin modules may also safely access node data. Enumeration 44*7aec1d6eScindi * occurs only during topo_snap_hold() where a per-topo_hdl_t lock prevents 45*7aec1d6eScindi * multi-threaded access to the topology trees. 46*7aec1d6eScindi * 47*7aec1d6eScindi * Like tree walking functions, method plugin modules have access to read-only 48*7aec1d6eScindi * node data but may make changes to property information. 49*7aec1d6eScindi * 50*7aec1d6eScindi * Node Interfaces 51*7aec1d6eScindi * 52*7aec1d6eScindi * Nodes are created when an enumerator calls topo_node_bind(). Prior to the 53*7aec1d6eScindi * call to topo_node_bind(), the caller should have reserved a range of 54*7aec1d6eScindi * node instances with topo_node_range_create(). topo_node_range_create() 55*7aec1d6eScindi * does not allocate any node resources but creates the infrastruture 56*7aec1d6eScindi * required for a fully populated topology level. This allows enumerators 57*7aec1d6eScindi * reading from a <scheme>-topology.xml file to parse the file for a range 58*7aec1d6eScindi * of resources before confirming the existence of a resource via a helper 59*7aec1d6eScindi * plugin. Only when the resource has been confirmed to exist should 60*7aec1d6eScindi * the node be bound. 61*7aec1d6eScindi * 62*7aec1d6eScindi * Node range and node linkage is only performed during enumeration when it 63*7aec1d6eScindi * is safe to change node hash lists and next pointers. Nodes and node ranges 64*7aec1d6eScindi * are deallocated when all references to the node have been released: 65*7aec1d6eScindi * last walk completes and topo_snap_rele() is called. 66*7aec1d6eScindi * 67*7aec1d6eScindi * Node Hash/Ranges 68*7aec1d6eScindi * 69*7aec1d6eScindi * Each parent node may have one or more ranges of child nodes. Each range 70*7aec1d6eScindi * serves as a hash list of like sibling nodes all with the same name but 71*7aec1d6eScindi * different instance numbers. A parent may have more than one node hash 72*7aec1d6eScindi * (child range). If that is the case, the hash lists are strung together to 73*7aec1d6eScindi * form sibling relationships between ranges. Hash/Ranges are sparsely 74*7aec1d6eScindi * populated with only nodes that have represented resources in the system. 75*7aec1d6eScindi */ 76*7aec1d6eScindi 77*7aec1d6eScindi #include <assert.h> 78*7aec1d6eScindi #include <pthread.h> 79*7aec1d6eScindi #include <strings.h> 80*7aec1d6eScindi #include <topo_alloc.h> 81*7aec1d6eScindi #include <topo_tree.h> 82*7aec1d6eScindi #include <topo_subr.h> 83*7aec1d6eScindi #include <topo_error.h> 84*7aec1d6eScindi 85*7aec1d6eScindi static void 86*7aec1d6eScindi topo_node_destroy(tnode_t *node) 87*7aec1d6eScindi { 88*7aec1d6eScindi int i; 89*7aec1d6eScindi tnode_t *pnode = node->tn_parent; 90*7aec1d6eScindi topo_nodehash_t *nhp; 91*7aec1d6eScindi topo_mod_t *hmod, *mod = node->tn_enum; 92*7aec1d6eScindi 93*7aec1d6eScindi if (node == NULL) 94*7aec1d6eScindi return; 95*7aec1d6eScindi 96*7aec1d6eScindi assert(node->tn_refs == 0); 97*7aec1d6eScindi 98*7aec1d6eScindi topo_dprintf(TOPO_DBG_TREE, "destroying node %s=%d\n", node->tn_name, 99*7aec1d6eScindi node->tn_instance); 100*7aec1d6eScindi /* 101*7aec1d6eScindi * If not a root node, remove this node from the parent's node hash 102*7aec1d6eScindi */ 103*7aec1d6eScindi 104*7aec1d6eScindi if (!(node->tn_state & TOPO_NODE_ROOT)) { 105*7aec1d6eScindi topo_node_lock(pnode); 106*7aec1d6eScindi 107*7aec1d6eScindi nhp = node->tn_phash; 108*7aec1d6eScindi for (i = 0; i < nhp->th_arrlen; i++) { 109*7aec1d6eScindi if (node == nhp->th_nodearr[i]) { 110*7aec1d6eScindi nhp->th_nodearr[i] = NULL; 111*7aec1d6eScindi 112*7aec1d6eScindi /* 113*7aec1d6eScindi * Release hold on parent 114*7aec1d6eScindi */ 115*7aec1d6eScindi --pnode->tn_refs; 116*7aec1d6eScindi if (pnode->tn_refs == 0) 117*7aec1d6eScindi topo_node_destroy(pnode); 118*7aec1d6eScindi } 119*7aec1d6eScindi } 120*7aec1d6eScindi topo_node_unlock(pnode); 121*7aec1d6eScindi } 122*7aec1d6eScindi 123*7aec1d6eScindi topo_node_unlock(node); 124*7aec1d6eScindi 125*7aec1d6eScindi /* 126*7aec1d6eScindi * Allow enumerator to clean-up private data and then release 127*7aec1d6eScindi * ref count 128*7aec1d6eScindi */ 129*7aec1d6eScindi if (mod->tm_info->tmi_release != NULL) 130*7aec1d6eScindi mod->tm_info->tmi_release(mod, node); 131*7aec1d6eScindi 132*7aec1d6eScindi topo_method_unregister_all(mod, node); 133*7aec1d6eScindi 134*7aec1d6eScindi /* 135*7aec1d6eScindi * Destroy all node hash lists 136*7aec1d6eScindi */ 137*7aec1d6eScindi while ((nhp = topo_list_next(&node->tn_children)) != NULL) { 138*7aec1d6eScindi for (i = 0; i < nhp->th_arrlen; i++) { 139*7aec1d6eScindi assert(nhp->th_nodearr[i] == NULL); 140*7aec1d6eScindi } 141*7aec1d6eScindi hmod = nhp->th_enum; 142*7aec1d6eScindi topo_mod_strfree(hmod, nhp->th_name); 143*7aec1d6eScindi topo_mod_free(hmod, nhp->th_nodearr, 144*7aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *)); 145*7aec1d6eScindi topo_list_delete(&node->tn_children, nhp); 146*7aec1d6eScindi topo_mod_free(hmod, nhp, sizeof (topo_nodehash_t)); 147*7aec1d6eScindi topo_mod_rele(hmod); 148*7aec1d6eScindi } 149*7aec1d6eScindi 150*7aec1d6eScindi /* 151*7aec1d6eScindi * Destroy all property data structures, free the node and release 152*7aec1d6eScindi * the module that created it 153*7aec1d6eScindi */ 154*7aec1d6eScindi topo_pgroup_destroy_all(node); 155*7aec1d6eScindi topo_mod_free(mod, node, sizeof (tnode_t)); 156*7aec1d6eScindi topo_mod_rele(mod); 157*7aec1d6eScindi } 158*7aec1d6eScindi 159*7aec1d6eScindi void 160*7aec1d6eScindi topo_node_lock(tnode_t *node) 161*7aec1d6eScindi { 162*7aec1d6eScindi (void) pthread_mutex_lock(&node->tn_lock); 163*7aec1d6eScindi } 164*7aec1d6eScindi 165*7aec1d6eScindi void 166*7aec1d6eScindi topo_node_unlock(tnode_t *node) 167*7aec1d6eScindi { 168*7aec1d6eScindi (void) pthread_mutex_unlock(&node->tn_lock); 169*7aec1d6eScindi } 170*7aec1d6eScindi 171*7aec1d6eScindi void 172*7aec1d6eScindi topo_node_hold(tnode_t *node) 173*7aec1d6eScindi { 174*7aec1d6eScindi topo_node_lock(node); 175*7aec1d6eScindi ++node->tn_refs; 176*7aec1d6eScindi topo_node_unlock(node); 177*7aec1d6eScindi } 178*7aec1d6eScindi 179*7aec1d6eScindi void 180*7aec1d6eScindi topo_node_rele(tnode_t *node) 181*7aec1d6eScindi { 182*7aec1d6eScindi topo_node_lock(node); 183*7aec1d6eScindi --node->tn_refs; 184*7aec1d6eScindi 185*7aec1d6eScindi /* 186*7aec1d6eScindi * Ok to remove this node from the topo tree and destroy it 187*7aec1d6eScindi */ 188*7aec1d6eScindi if (node->tn_refs == 0) 189*7aec1d6eScindi topo_node_destroy(node); 190*7aec1d6eScindi else 191*7aec1d6eScindi topo_node_unlock(node); 192*7aec1d6eScindi } 193*7aec1d6eScindi 194*7aec1d6eScindi char * 195*7aec1d6eScindi topo_node_name(tnode_t *node) 196*7aec1d6eScindi { 197*7aec1d6eScindi return (node->tn_name); 198*7aec1d6eScindi } 199*7aec1d6eScindi 200*7aec1d6eScindi topo_instance_t 201*7aec1d6eScindi topo_node_instance(tnode_t *node) 202*7aec1d6eScindi { 203*7aec1d6eScindi return (node->tn_instance); 204*7aec1d6eScindi } 205*7aec1d6eScindi 206*7aec1d6eScindi void * 207*7aec1d6eScindi topo_node_private(tnode_t *node) 208*7aec1d6eScindi { 209*7aec1d6eScindi return (node->tn_priv); 210*7aec1d6eScindi } 211*7aec1d6eScindi 212*7aec1d6eScindi static int 213*7aec1d6eScindi node_create_seterror(topo_mod_t *mod, tnode_t *pnode, topo_nodehash_t *nhp, 214*7aec1d6eScindi int err) 215*7aec1d6eScindi { 216*7aec1d6eScindi topo_node_unlock(pnode); 217*7aec1d6eScindi 218*7aec1d6eScindi topo_dprintf(TOPO_DBG_ERR, "unable to insert child:" 219*7aec1d6eScindi "%s\n", topo_strerror(err)); 220*7aec1d6eScindi 221*7aec1d6eScindi if (nhp != NULL) { 222*7aec1d6eScindi if (nhp->th_name != NULL) 223*7aec1d6eScindi topo_mod_strfree(mod, nhp->th_name); 224*7aec1d6eScindi if (nhp->th_nodearr != NULL) { 225*7aec1d6eScindi topo_mod_free(mod, nhp->th_nodearr, 226*7aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *)); 227*7aec1d6eScindi } 228*7aec1d6eScindi topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); 229*7aec1d6eScindi } 230*7aec1d6eScindi 231*7aec1d6eScindi return (topo_mod_seterrno(mod, err)); 232*7aec1d6eScindi } 233*7aec1d6eScindi 234*7aec1d6eScindi int 235*7aec1d6eScindi topo_node_range_create(topo_mod_t *mod, tnode_t *pnode, const char *name, 236*7aec1d6eScindi topo_instance_t min, topo_instance_t max) 237*7aec1d6eScindi { 238*7aec1d6eScindi topo_nodehash_t *nhp; 239*7aec1d6eScindi 240*7aec1d6eScindi topo_node_lock(pnode); 241*7aec1d6eScindi 242*7aec1d6eScindi assert((pnode->tn_state & TOPO_NODE_BOUND) || 243*7aec1d6eScindi (pnode->tn_state & TOPO_NODE_ROOT)); 244*7aec1d6eScindi 245*7aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 246*7aec1d6eScindi nhp = topo_list_next(nhp)) { 247*7aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) 248*7aec1d6eScindi return (node_create_seterror(mod, pnode, NULL, 249*7aec1d6eScindi ETOPO_NODE_DUP)); 250*7aec1d6eScindi } 251*7aec1d6eScindi 252*7aec1d6eScindi if (min < 0 || max < min) 253*7aec1d6eScindi return (node_create_seterror(mod, pnode, NULL, 254*7aec1d6eScindi ETOPO_NODE_INVAL)); 255*7aec1d6eScindi 256*7aec1d6eScindi if ((nhp = topo_mod_zalloc(mod, sizeof (topo_nodehash_t))) == NULL) 257*7aec1d6eScindi return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); 258*7aec1d6eScindi 259*7aec1d6eScindi if ((nhp->th_name = topo_mod_strdup(mod, name)) == NULL) 260*7aec1d6eScindi return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); 261*7aec1d6eScindi 262*7aec1d6eScindi nhp->th_arrlen = max - min + 1; 263*7aec1d6eScindi 264*7aec1d6eScindi if ((nhp->th_nodearr = topo_mod_zalloc(mod, 265*7aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *))) == NULL) 266*7aec1d6eScindi return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); 267*7aec1d6eScindi 268*7aec1d6eScindi nhp->th_range.tr_min = min; 269*7aec1d6eScindi nhp->th_range.tr_max = max; 270*7aec1d6eScindi nhp->th_enum = mod; 271*7aec1d6eScindi topo_mod_hold(mod); 272*7aec1d6eScindi 273*7aec1d6eScindi /* 274*7aec1d6eScindi * Add these nodes to parent child list 275*7aec1d6eScindi */ 276*7aec1d6eScindi topo_list_append(&pnode->tn_children, nhp); 277*7aec1d6eScindi topo_node_unlock(pnode); 278*7aec1d6eScindi 279*7aec1d6eScindi topo_dprintf(TOPO_DBG_MOD, "created node range %s[%d-%d]\n", name, 280*7aec1d6eScindi min, max); 281*7aec1d6eScindi 282*7aec1d6eScindi return (0); 283*7aec1d6eScindi } 284*7aec1d6eScindi 285*7aec1d6eScindi void 286*7aec1d6eScindi topo_node_range_destroy(tnode_t *pnode, const char *name) 287*7aec1d6eScindi { 288*7aec1d6eScindi int i; 289*7aec1d6eScindi topo_nodehash_t *nhp; 290*7aec1d6eScindi topo_mod_t *mod; 291*7aec1d6eScindi 292*7aec1d6eScindi topo_node_lock(pnode); 293*7aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 294*7aec1d6eScindi nhp = topo_list_next(nhp)) { 295*7aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) { 296*7aec1d6eScindi break; 297*7aec1d6eScindi } 298*7aec1d6eScindi } 299*7aec1d6eScindi 300*7aec1d6eScindi if (nhp == NULL) { 301*7aec1d6eScindi topo_node_unlock(pnode); 302*7aec1d6eScindi return; 303*7aec1d6eScindi } 304*7aec1d6eScindi 305*7aec1d6eScindi topo_list_delete(&pnode->tn_children, nhp); 306*7aec1d6eScindi topo_node_unlock(pnode); 307*7aec1d6eScindi 308*7aec1d6eScindi /* 309*7aec1d6eScindi * Should be an empty node range 310*7aec1d6eScindi */ 311*7aec1d6eScindi for (i = 0; i < nhp->th_arrlen; i++) { 312*7aec1d6eScindi topo_node_unbind(nhp->th_nodearr[i]); 313*7aec1d6eScindi } 314*7aec1d6eScindi 315*7aec1d6eScindi mod = nhp->th_enum; 316*7aec1d6eScindi if (nhp->th_name != NULL) 317*7aec1d6eScindi topo_mod_strfree(mod, nhp->th_name); 318*7aec1d6eScindi if (nhp->th_nodearr != NULL) { 319*7aec1d6eScindi topo_mod_free(mod, nhp->th_nodearr, 320*7aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *)); 321*7aec1d6eScindi } 322*7aec1d6eScindi topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); 323*7aec1d6eScindi topo_mod_rele(mod); 324*7aec1d6eScindi 325*7aec1d6eScindi } 326*7aec1d6eScindi 327*7aec1d6eScindi tnode_t * 328*7aec1d6eScindi topo_node_lookup(tnode_t *pnode, const char *name, topo_instance_t inst) 329*7aec1d6eScindi { 330*7aec1d6eScindi int h; 331*7aec1d6eScindi tnode_t *node; 332*7aec1d6eScindi topo_nodehash_t *nhp; 333*7aec1d6eScindi 334*7aec1d6eScindi topo_node_lock(pnode); 335*7aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 336*7aec1d6eScindi nhp = topo_list_next(nhp)) { 337*7aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) { 338*7aec1d6eScindi 339*7aec1d6eScindi if (inst > nhp->th_range.tr_max || 340*7aec1d6eScindi inst < nhp->th_range.tr_min) { 341*7aec1d6eScindi topo_node_unlock(pnode); 342*7aec1d6eScindi return (NULL); 343*7aec1d6eScindi } 344*7aec1d6eScindi 345*7aec1d6eScindi h = topo_node_hash(nhp, inst); 346*7aec1d6eScindi node = nhp->th_nodearr[h]; 347*7aec1d6eScindi topo_node_unlock(pnode); 348*7aec1d6eScindi return (node); 349*7aec1d6eScindi } 350*7aec1d6eScindi } 351*7aec1d6eScindi topo_node_unlock(pnode); 352*7aec1d6eScindi 353*7aec1d6eScindi return (NULL); 354*7aec1d6eScindi } 355*7aec1d6eScindi 356*7aec1d6eScindi int 357*7aec1d6eScindi topo_node_hash(topo_nodehash_t *nhp, topo_instance_t inst) 358*7aec1d6eScindi { 359*7aec1d6eScindi return (nhp->th_range.tr_max == 0 ? 360*7aec1d6eScindi nhp->th_range.tr_max : inst % (nhp->th_range.tr_max + 1)); 361*7aec1d6eScindi } 362*7aec1d6eScindi 363*7aec1d6eScindi static tnode_t * 364*7aec1d6eScindi node_bind_seterror(topo_mod_t *mod, tnode_t *pnode, tnode_t *node, int err) 365*7aec1d6eScindi { 366*7aec1d6eScindi topo_node_unlock(pnode); 367*7aec1d6eScindi 368*7aec1d6eScindi (void) topo_mod_seterrno(mod, err); 369*7aec1d6eScindi 370*7aec1d6eScindi if (node == NULL) 371*7aec1d6eScindi return (NULL); 372*7aec1d6eScindi 373*7aec1d6eScindi topo_dprintf(TOPO_DBG_ERR, "unable to bind %s=%d: " 374*7aec1d6eScindi "%s\n", (node->tn_name != NULL ? node->tn_name : "unknown"), 375*7aec1d6eScindi node->tn_instance, topo_strerror(err)); 376*7aec1d6eScindi 377*7aec1d6eScindi topo_node_lock(node); /* expected to be locked */ 378*7aec1d6eScindi topo_node_destroy(node); 379*7aec1d6eScindi 380*7aec1d6eScindi return (NULL); 381*7aec1d6eScindi } 382*7aec1d6eScindi 383*7aec1d6eScindi tnode_t * 384*7aec1d6eScindi topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, 385*7aec1d6eScindi topo_instance_t inst, nvlist_t *fmri, void *priv) 386*7aec1d6eScindi { 387*7aec1d6eScindi int h, err; 388*7aec1d6eScindi tnode_t *node; 389*7aec1d6eScindi topo_nodehash_t *nhp; 390*7aec1d6eScindi 391*7aec1d6eScindi topo_node_lock(pnode); 392*7aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 393*7aec1d6eScindi nhp = topo_list_next(nhp)) { 394*7aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) { 395*7aec1d6eScindi 396*7aec1d6eScindi if (inst > nhp->th_range.tr_max || 397*7aec1d6eScindi inst < nhp->th_range.tr_min) 398*7aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, 399*7aec1d6eScindi ETOPO_NODE_INVAL)); 400*7aec1d6eScindi 401*7aec1d6eScindi h = topo_node_hash(nhp, inst); 402*7aec1d6eScindi if (nhp->th_nodearr[h] != NULL) 403*7aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, 404*7aec1d6eScindi ETOPO_NODE_BOUND)); 405*7aec1d6eScindi else 406*7aec1d6eScindi break; 407*7aec1d6eScindi 408*7aec1d6eScindi } 409*7aec1d6eScindi } 410*7aec1d6eScindi 411*7aec1d6eScindi if (nhp == NULL) 412*7aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_NOENT)); 413*7aec1d6eScindi 414*7aec1d6eScindi if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL) 415*7aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, ETOPO_NOMEM)); 416*7aec1d6eScindi 417*7aec1d6eScindi (void) pthread_mutex_init(&node->tn_lock, NULL); 418*7aec1d6eScindi 419*7aec1d6eScindi node->tn_enum = mod; 420*7aec1d6eScindi node->tn_hdl = mod->tm_hdl; 421*7aec1d6eScindi node->tn_parent = pnode; 422*7aec1d6eScindi node->tn_name = nhp->th_name; 423*7aec1d6eScindi node->tn_instance = inst; 424*7aec1d6eScindi node->tn_phash = nhp; 425*7aec1d6eScindi node->tn_refs = 0; 426*7aec1d6eScindi 427*7aec1d6eScindi /* Ref count module that bound this node */ 428*7aec1d6eScindi topo_mod_hold(mod); 429*7aec1d6eScindi 430*7aec1d6eScindi if (fmri == NULL) 431*7aec1d6eScindi return (node_bind_seterror(mod, pnode, node, ETOPO_NODE_INVAL)); 432*7aec1d6eScindi 433*7aec1d6eScindi if (topo_pgroup_create(node, TOPO_PGROUP_PROTOCOL, 434*7aec1d6eScindi TOPO_STABILITY_PRIVATE, &err) < 0) 435*7aec1d6eScindi return (node_bind_seterror(mod, pnode, node, err)); 436*7aec1d6eScindi 437*7aec1d6eScindi if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, 438*7aec1d6eScindi TOPO_PROP_SET_ONCE, fmri, &err) < 0) 439*7aec1d6eScindi return (node_bind_seterror(mod, pnode, node, err)); 440*7aec1d6eScindi 441*7aec1d6eScindi topo_dprintf(TOPO_DBG_MOD, "node bound %s=%d\n", node->tn_name, 442*7aec1d6eScindi node->tn_instance); 443*7aec1d6eScindi 444*7aec1d6eScindi node->tn_state |= TOPO_NODE_BOUND; 445*7aec1d6eScindi node->tn_priv = priv; 446*7aec1d6eScindi 447*7aec1d6eScindi topo_node_hold(node); 448*7aec1d6eScindi nhp->th_nodearr[h] = node; 449*7aec1d6eScindi ++pnode->tn_refs; 450*7aec1d6eScindi topo_node_unlock(pnode); 451*7aec1d6eScindi 452*7aec1d6eScindi if (topo_pgroup_create(node, TOPO_PGROUP_SYSTEM, 453*7aec1d6eScindi TOPO_STABILITY_PRIVATE, &err) == 0) { 454*7aec1d6eScindi (void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM, 455*7aec1d6eScindi TOPO_PROP_PLATFORM, &err); 456*7aec1d6eScindi (void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM, 457*7aec1d6eScindi TOPO_PROP_ISA, &err); 458*7aec1d6eScindi (void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM, 459*7aec1d6eScindi TOPO_PROP_MACHINE, &err); 460*7aec1d6eScindi } 461*7aec1d6eScindi 462*7aec1d6eScindi return (node); 463*7aec1d6eScindi } 464*7aec1d6eScindi 465*7aec1d6eScindi void 466*7aec1d6eScindi topo_node_unbind(tnode_t *node) 467*7aec1d6eScindi { 468*7aec1d6eScindi if (node == NULL) 469*7aec1d6eScindi return; 470*7aec1d6eScindi 471*7aec1d6eScindi topo_node_lock(node); 472*7aec1d6eScindi if (!(node->tn_state & TOPO_NODE_BOUND)) { 473*7aec1d6eScindi topo_node_unlock(node); 474*7aec1d6eScindi return; 475*7aec1d6eScindi } 476*7aec1d6eScindi 477*7aec1d6eScindi node->tn_state &= ~TOPO_NODE_BOUND; 478*7aec1d6eScindi topo_node_unlock(node); 479*7aec1d6eScindi 480*7aec1d6eScindi topo_node_rele(node); 481*7aec1d6eScindi } 482*7aec1d6eScindi 483*7aec1d6eScindi /*ARGSUSED*/ 484*7aec1d6eScindi int 485*7aec1d6eScindi topo_node_present(tnode_t *node) 486*7aec1d6eScindi { 487*7aec1d6eScindi return (0); 488*7aec1d6eScindi } 489*7aec1d6eScindi 490*7aec1d6eScindi /*ARGSUSED*/ 491*7aec1d6eScindi int 492*7aec1d6eScindi topo_node_contains(tnode_t *er, tnode_t *ee) 493*7aec1d6eScindi { 494*7aec1d6eScindi return (0); 495*7aec1d6eScindi } 496*7aec1d6eScindi 497*7aec1d6eScindi /*ARGSUSED*/ 498*7aec1d6eScindi int 499*7aec1d6eScindi topo_node_unusable(tnode_t *node) 500*7aec1d6eScindi { 501*7aec1d6eScindi return (0); 502*7aec1d6eScindi } 503