17aec1d6eScindi /* 27aec1d6eScindi * CDDL HEADER START 37aec1d6eScindi * 47aec1d6eScindi * The contents of this file are subject to the terms of the 5*0eb822a1Scindi * Common Development and Distribution License (the "License"). 6*0eb822a1Scindi * You may not use this file except in compliance with the License. 77aec1d6eScindi * 87aec1d6eScindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97aec1d6eScindi * or http://www.opensolaris.org/os/licensing. 107aec1d6eScindi * See the License for the specific language governing permissions 117aec1d6eScindi * and limitations under the License. 127aec1d6eScindi * 137aec1d6eScindi * When distributing Covered Code, include this CDDL HEADER in each 147aec1d6eScindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157aec1d6eScindi * If applicable, add the following below this CDDL HEADER, with the 167aec1d6eScindi * fields enclosed by brackets "[]" replaced with your own identifying 177aec1d6eScindi * information: Portions Copyright [yyyy] [name of copyright owner] 187aec1d6eScindi * 197aec1d6eScindi * CDDL HEADER END 207aec1d6eScindi */ 217aec1d6eScindi /* 227aec1d6eScindi * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237aec1d6eScindi * Use is subject to license terms. 247aec1d6eScindi */ 257aec1d6eScindi 267aec1d6eScindi #pragma ident "%Z%%M% %I% %E% SMI" 277aec1d6eScindi 287aec1d6eScindi /* 297aec1d6eScindi * Topology Nodes 307aec1d6eScindi * 317aec1d6eScindi * Topology nodes, tnode_t, are data structures containing per-FMRI 327aec1d6eScindi * information and are linked together to form the topology tree. 337aec1d6eScindi * Nodes are created during the enumeration process of topo_snap_hold() 347aec1d6eScindi * and destroyed during topo_snap_rele(). For the most part, tnode_t data 357aec1d6eScindi * is read-only and no lock protection is required. Nodes are 367aec1d6eScindi * held in place during tree walk functions. Tree walk functions 377aec1d6eScindi * may access node data safely without locks. The exception to this rule 387aec1d6eScindi * is data associated with node properties (topo_prop.c). Properties 397aec1d6eScindi * may change at anytime and are protected by a per-property locking 407aec1d6eScindi * strategy. 417aec1d6eScindi * 427aec1d6eScindi * Enumerator plugin modules may also safely access node data. Enumeration 437aec1d6eScindi * occurs only during topo_snap_hold() where a per-topo_hdl_t lock prevents 447aec1d6eScindi * multi-threaded access to the topology trees. 457aec1d6eScindi * 467aec1d6eScindi * Like tree walking functions, method plugin modules have access to read-only 477aec1d6eScindi * node data but may make changes to property information. 487aec1d6eScindi * 497aec1d6eScindi * Node Interfaces 507aec1d6eScindi * 517aec1d6eScindi * Nodes are created when an enumerator calls topo_node_bind(). Prior to the 527aec1d6eScindi * call to topo_node_bind(), the caller should have reserved a range of 537aec1d6eScindi * node instances with topo_node_range_create(). topo_node_range_create() 547aec1d6eScindi * does not allocate any node resources but creates the infrastruture 557aec1d6eScindi * required for a fully populated topology level. This allows enumerators 567aec1d6eScindi * reading from a <scheme>-topology.xml file to parse the file for a range 577aec1d6eScindi * of resources before confirming the existence of a resource via a helper 587aec1d6eScindi * plugin. Only when the resource has been confirmed to exist should 597aec1d6eScindi * the node be bound. 607aec1d6eScindi * 617aec1d6eScindi * Node range and node linkage is only performed during enumeration when it 627aec1d6eScindi * is safe to change node hash lists and next pointers. Nodes and node ranges 637aec1d6eScindi * are deallocated when all references to the node have been released: 647aec1d6eScindi * last walk completes and topo_snap_rele() is called. 657aec1d6eScindi * 667aec1d6eScindi * Node Hash/Ranges 677aec1d6eScindi * 687aec1d6eScindi * Each parent node may have one or more ranges of child nodes. Each range 697aec1d6eScindi * serves as a hash list of like sibling nodes all with the same name but 707aec1d6eScindi * different instance numbers. A parent may have more than one node hash 717aec1d6eScindi * (child range). If that is the case, the hash lists are strung together to 727aec1d6eScindi * form sibling relationships between ranges. Hash/Ranges are sparsely 737aec1d6eScindi * populated with only nodes that have represented resources in the system. 747aec1d6eScindi */ 757aec1d6eScindi 767aec1d6eScindi #include <assert.h> 777aec1d6eScindi #include <pthread.h> 787aec1d6eScindi #include <strings.h> 79*0eb822a1Scindi #include <sys/fm/protocol.h> 807aec1d6eScindi #include <topo_alloc.h> 817aec1d6eScindi #include <topo_error.h> 82*0eb822a1Scindi #include <topo_method.h> 83*0eb822a1Scindi #include <topo_subr.h> 84*0eb822a1Scindi #include <topo_tree.h> 85*0eb822a1Scindi 86*0eb822a1Scindi static topo_pgroup_info_t protocol_pgroup = { 87*0eb822a1Scindi TOPO_PGROUP_PROTOCOL, 88*0eb822a1Scindi TOPO_STABILITY_PRIVATE, 89*0eb822a1Scindi TOPO_STABILITY_PRIVATE, 90*0eb822a1Scindi 1 91*0eb822a1Scindi }; 92*0eb822a1Scindi 93*0eb822a1Scindi static const topo_pgroup_info_t auth_pgroup = { 94*0eb822a1Scindi FM_FMRI_AUTHORITY, 95*0eb822a1Scindi TOPO_STABILITY_PRIVATE, 96*0eb822a1Scindi TOPO_STABILITY_PRIVATE, 97*0eb822a1Scindi 1 98*0eb822a1Scindi }; 997aec1d6eScindi 1007aec1d6eScindi static void 1017aec1d6eScindi topo_node_destroy(tnode_t *node) 1027aec1d6eScindi { 1037aec1d6eScindi int i; 1047aec1d6eScindi tnode_t *pnode = node->tn_parent; 1057aec1d6eScindi topo_nodehash_t *nhp; 1067aec1d6eScindi topo_mod_t *hmod, *mod = node->tn_enum; 1077aec1d6eScindi 1087aec1d6eScindi if (node == NULL) 1097aec1d6eScindi return; 1107aec1d6eScindi 1117aec1d6eScindi assert(node->tn_refs == 0); 1127aec1d6eScindi 1137aec1d6eScindi /* 1147aec1d6eScindi * If not a root node, remove this node from the parent's node hash 1157aec1d6eScindi */ 1167aec1d6eScindi 1177aec1d6eScindi if (!(node->tn_state & TOPO_NODE_ROOT)) { 1187aec1d6eScindi topo_node_lock(pnode); 1197aec1d6eScindi 1207aec1d6eScindi nhp = node->tn_phash; 1217aec1d6eScindi for (i = 0; i < nhp->th_arrlen; i++) { 1227aec1d6eScindi if (node == nhp->th_nodearr[i]) { 1237aec1d6eScindi nhp->th_nodearr[i] = NULL; 1247aec1d6eScindi 1257aec1d6eScindi /* 1267aec1d6eScindi * Release hold on parent 1277aec1d6eScindi */ 1287aec1d6eScindi --pnode->tn_refs; 1297aec1d6eScindi if (pnode->tn_refs == 0) 1307aec1d6eScindi topo_node_destroy(pnode); 1317aec1d6eScindi } 1327aec1d6eScindi } 1337aec1d6eScindi topo_node_unlock(pnode); 1347aec1d6eScindi } 1357aec1d6eScindi 1367aec1d6eScindi topo_node_unlock(node); 1377aec1d6eScindi 1387aec1d6eScindi /* 1397aec1d6eScindi * Allow enumerator to clean-up private data and then release 1407aec1d6eScindi * ref count 1417aec1d6eScindi */ 142*0eb822a1Scindi if (mod->tm_info->tmi_ops->tmo_release != NULL) 143*0eb822a1Scindi mod->tm_info->tmi_ops->tmo_release(mod, node); 1447aec1d6eScindi 1457aec1d6eScindi topo_method_unregister_all(mod, node); 1467aec1d6eScindi 1477aec1d6eScindi /* 1487aec1d6eScindi * Destroy all node hash lists 1497aec1d6eScindi */ 1507aec1d6eScindi while ((nhp = topo_list_next(&node->tn_children)) != NULL) { 1517aec1d6eScindi for (i = 0; i < nhp->th_arrlen; i++) { 1527aec1d6eScindi assert(nhp->th_nodearr[i] == NULL); 1537aec1d6eScindi } 1547aec1d6eScindi hmod = nhp->th_enum; 1557aec1d6eScindi topo_mod_strfree(hmod, nhp->th_name); 1567aec1d6eScindi topo_mod_free(hmod, nhp->th_nodearr, 1577aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *)); 1587aec1d6eScindi topo_list_delete(&node->tn_children, nhp); 1597aec1d6eScindi topo_mod_free(hmod, nhp, sizeof (topo_nodehash_t)); 1607aec1d6eScindi topo_mod_rele(hmod); 1617aec1d6eScindi } 1627aec1d6eScindi 1637aec1d6eScindi /* 1647aec1d6eScindi * Destroy all property data structures, free the node and release 1657aec1d6eScindi * the module that created it 1667aec1d6eScindi */ 1677aec1d6eScindi topo_pgroup_destroy_all(node); 1687aec1d6eScindi topo_mod_free(mod, node, sizeof (tnode_t)); 1697aec1d6eScindi topo_mod_rele(mod); 1707aec1d6eScindi } 1717aec1d6eScindi 1727aec1d6eScindi void 1737aec1d6eScindi topo_node_lock(tnode_t *node) 1747aec1d6eScindi { 1757aec1d6eScindi (void) pthread_mutex_lock(&node->tn_lock); 1767aec1d6eScindi } 1777aec1d6eScindi 1787aec1d6eScindi void 1797aec1d6eScindi topo_node_unlock(tnode_t *node) 1807aec1d6eScindi { 1817aec1d6eScindi (void) pthread_mutex_unlock(&node->tn_lock); 1827aec1d6eScindi } 1837aec1d6eScindi 1847aec1d6eScindi void 1857aec1d6eScindi topo_node_hold(tnode_t *node) 1867aec1d6eScindi { 1877aec1d6eScindi topo_node_lock(node); 1887aec1d6eScindi ++node->tn_refs; 1897aec1d6eScindi topo_node_unlock(node); 1907aec1d6eScindi } 1917aec1d6eScindi 1927aec1d6eScindi void 1937aec1d6eScindi topo_node_rele(tnode_t *node) 1947aec1d6eScindi { 1957aec1d6eScindi topo_node_lock(node); 1967aec1d6eScindi --node->tn_refs; 1977aec1d6eScindi 1987aec1d6eScindi /* 1997aec1d6eScindi * Ok to remove this node from the topo tree and destroy it 2007aec1d6eScindi */ 2017aec1d6eScindi if (node->tn_refs == 0) 2027aec1d6eScindi topo_node_destroy(node); 2037aec1d6eScindi else 2047aec1d6eScindi topo_node_unlock(node); 2057aec1d6eScindi } 2067aec1d6eScindi 2077aec1d6eScindi char * 2087aec1d6eScindi topo_node_name(tnode_t *node) 2097aec1d6eScindi { 2107aec1d6eScindi return (node->tn_name); 2117aec1d6eScindi } 2127aec1d6eScindi 2137aec1d6eScindi topo_instance_t 2147aec1d6eScindi topo_node_instance(tnode_t *node) 2157aec1d6eScindi { 2167aec1d6eScindi return (node->tn_instance); 2177aec1d6eScindi } 2187aec1d6eScindi 219*0eb822a1Scindi void 220*0eb822a1Scindi topo_node_setspecific(tnode_t *node, void *data) 221*0eb822a1Scindi { 222*0eb822a1Scindi node->tn_priv = data; 223*0eb822a1Scindi } 224*0eb822a1Scindi 2257aec1d6eScindi void * 226*0eb822a1Scindi topo_node_getspecific(tnode_t *node) 2277aec1d6eScindi { 2287aec1d6eScindi return (node->tn_priv); 2297aec1d6eScindi } 2307aec1d6eScindi 2317aec1d6eScindi static int 2327aec1d6eScindi node_create_seterror(topo_mod_t *mod, tnode_t *pnode, topo_nodehash_t *nhp, 2337aec1d6eScindi int err) 2347aec1d6eScindi { 2357aec1d6eScindi topo_node_unlock(pnode); 2367aec1d6eScindi 237*0eb822a1Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, "unable to insert child:" 2387aec1d6eScindi "%s\n", topo_strerror(err)); 2397aec1d6eScindi 2407aec1d6eScindi if (nhp != NULL) { 2417aec1d6eScindi if (nhp->th_name != NULL) 2427aec1d6eScindi topo_mod_strfree(mod, nhp->th_name); 2437aec1d6eScindi if (nhp->th_nodearr != NULL) { 2447aec1d6eScindi topo_mod_free(mod, nhp->th_nodearr, 2457aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *)); 2467aec1d6eScindi } 2477aec1d6eScindi topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); 2487aec1d6eScindi } 2497aec1d6eScindi 2507aec1d6eScindi return (topo_mod_seterrno(mod, err)); 2517aec1d6eScindi } 2527aec1d6eScindi 2537aec1d6eScindi int 2547aec1d6eScindi topo_node_range_create(topo_mod_t *mod, tnode_t *pnode, const char *name, 2557aec1d6eScindi topo_instance_t min, topo_instance_t max) 2567aec1d6eScindi { 2577aec1d6eScindi topo_nodehash_t *nhp; 2587aec1d6eScindi 2597aec1d6eScindi topo_node_lock(pnode); 2607aec1d6eScindi 2617aec1d6eScindi assert((pnode->tn_state & TOPO_NODE_BOUND) || 2627aec1d6eScindi (pnode->tn_state & TOPO_NODE_ROOT)); 2637aec1d6eScindi 2647aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 2657aec1d6eScindi nhp = topo_list_next(nhp)) { 2667aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) 2677aec1d6eScindi return (node_create_seterror(mod, pnode, NULL, 2687aec1d6eScindi ETOPO_NODE_DUP)); 2697aec1d6eScindi } 2707aec1d6eScindi 2717aec1d6eScindi if (min < 0 || max < min) 2727aec1d6eScindi return (node_create_seterror(mod, pnode, NULL, 2737aec1d6eScindi ETOPO_NODE_INVAL)); 2747aec1d6eScindi 2757aec1d6eScindi if ((nhp = topo_mod_zalloc(mod, sizeof (topo_nodehash_t))) == NULL) 2767aec1d6eScindi return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); 2777aec1d6eScindi 2787aec1d6eScindi if ((nhp->th_name = topo_mod_strdup(mod, name)) == NULL) 2797aec1d6eScindi return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); 2807aec1d6eScindi 2817aec1d6eScindi nhp->th_arrlen = max - min + 1; 2827aec1d6eScindi 2837aec1d6eScindi if ((nhp->th_nodearr = topo_mod_zalloc(mod, 2847aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *))) == NULL) 2857aec1d6eScindi return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); 2867aec1d6eScindi 2877aec1d6eScindi nhp->th_range.tr_min = min; 2887aec1d6eScindi nhp->th_range.tr_max = max; 2897aec1d6eScindi nhp->th_enum = mod; 2907aec1d6eScindi topo_mod_hold(mod); 2917aec1d6eScindi 2927aec1d6eScindi /* 2937aec1d6eScindi * Add these nodes to parent child list 2947aec1d6eScindi */ 2957aec1d6eScindi topo_list_append(&pnode->tn_children, nhp); 2967aec1d6eScindi topo_node_unlock(pnode); 2977aec1d6eScindi 298*0eb822a1Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, 299*0eb822a1Scindi "created node range %s[%d-%d]\n", name, min, max); 3007aec1d6eScindi 3017aec1d6eScindi return (0); 3027aec1d6eScindi } 3037aec1d6eScindi 3047aec1d6eScindi void 3057aec1d6eScindi topo_node_range_destroy(tnode_t *pnode, const char *name) 3067aec1d6eScindi { 3077aec1d6eScindi int i; 3087aec1d6eScindi topo_nodehash_t *nhp; 3097aec1d6eScindi topo_mod_t *mod; 3107aec1d6eScindi 3117aec1d6eScindi topo_node_lock(pnode); 3127aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 3137aec1d6eScindi nhp = topo_list_next(nhp)) { 3147aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) { 3157aec1d6eScindi break; 3167aec1d6eScindi } 3177aec1d6eScindi } 3187aec1d6eScindi 3197aec1d6eScindi if (nhp == NULL) { 3207aec1d6eScindi topo_node_unlock(pnode); 3217aec1d6eScindi return; 3227aec1d6eScindi } 3237aec1d6eScindi 3247aec1d6eScindi topo_list_delete(&pnode->tn_children, nhp); 3257aec1d6eScindi topo_node_unlock(pnode); 3267aec1d6eScindi 3277aec1d6eScindi /* 3287aec1d6eScindi * Should be an empty node range 3297aec1d6eScindi */ 3307aec1d6eScindi for (i = 0; i < nhp->th_arrlen; i++) { 3317aec1d6eScindi topo_node_unbind(nhp->th_nodearr[i]); 3327aec1d6eScindi } 3337aec1d6eScindi 3347aec1d6eScindi mod = nhp->th_enum; 3357aec1d6eScindi if (nhp->th_name != NULL) 3367aec1d6eScindi topo_mod_strfree(mod, nhp->th_name); 3377aec1d6eScindi if (nhp->th_nodearr != NULL) { 3387aec1d6eScindi topo_mod_free(mod, nhp->th_nodearr, 3397aec1d6eScindi nhp->th_arrlen * sizeof (tnode_t *)); 3407aec1d6eScindi } 3417aec1d6eScindi topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); 3427aec1d6eScindi topo_mod_rele(mod); 3437aec1d6eScindi 3447aec1d6eScindi } 3457aec1d6eScindi 3467aec1d6eScindi tnode_t * 3477aec1d6eScindi topo_node_lookup(tnode_t *pnode, const char *name, topo_instance_t inst) 3487aec1d6eScindi { 3497aec1d6eScindi int h; 3507aec1d6eScindi tnode_t *node; 3517aec1d6eScindi topo_nodehash_t *nhp; 3527aec1d6eScindi 3537aec1d6eScindi topo_node_lock(pnode); 3547aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 3557aec1d6eScindi nhp = topo_list_next(nhp)) { 3567aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) { 3577aec1d6eScindi 3587aec1d6eScindi if (inst > nhp->th_range.tr_max || 3597aec1d6eScindi inst < nhp->th_range.tr_min) { 3607aec1d6eScindi topo_node_unlock(pnode); 3617aec1d6eScindi return (NULL); 3627aec1d6eScindi } 3637aec1d6eScindi 3647aec1d6eScindi h = topo_node_hash(nhp, inst); 3657aec1d6eScindi node = nhp->th_nodearr[h]; 3667aec1d6eScindi topo_node_unlock(pnode); 3677aec1d6eScindi return (node); 3687aec1d6eScindi } 3697aec1d6eScindi } 3707aec1d6eScindi topo_node_unlock(pnode); 3717aec1d6eScindi 3727aec1d6eScindi return (NULL); 3737aec1d6eScindi } 3747aec1d6eScindi 3757aec1d6eScindi int 3767aec1d6eScindi topo_node_hash(topo_nodehash_t *nhp, topo_instance_t inst) 3777aec1d6eScindi { 3787aec1d6eScindi return (nhp->th_range.tr_max == 0 ? 3797aec1d6eScindi nhp->th_range.tr_max : inst % (nhp->th_range.tr_max + 1)); 3807aec1d6eScindi } 3817aec1d6eScindi 3827aec1d6eScindi static tnode_t * 3837aec1d6eScindi node_bind_seterror(topo_mod_t *mod, tnode_t *pnode, tnode_t *node, int err) 3847aec1d6eScindi { 3857aec1d6eScindi topo_node_unlock(pnode); 3867aec1d6eScindi 3877aec1d6eScindi (void) topo_mod_seterrno(mod, err); 3887aec1d6eScindi 3897aec1d6eScindi if (node == NULL) 3907aec1d6eScindi return (NULL); 3917aec1d6eScindi 392*0eb822a1Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_ERR, "unable to bind %s=%d: " 3937aec1d6eScindi "%s\n", (node->tn_name != NULL ? node->tn_name : "unknown"), 3947aec1d6eScindi node->tn_instance, topo_strerror(err)); 3957aec1d6eScindi 3967aec1d6eScindi topo_node_lock(node); /* expected to be locked */ 3977aec1d6eScindi topo_node_destroy(node); 3987aec1d6eScindi 3997aec1d6eScindi return (NULL); 4007aec1d6eScindi } 4017aec1d6eScindi 4027aec1d6eScindi tnode_t * 4037aec1d6eScindi topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, 404*0eb822a1Scindi topo_instance_t inst, nvlist_t *fmri) 4057aec1d6eScindi { 4067aec1d6eScindi int h, err; 4077aec1d6eScindi tnode_t *node; 4087aec1d6eScindi topo_nodehash_t *nhp; 4097aec1d6eScindi 4107aec1d6eScindi topo_node_lock(pnode); 4117aec1d6eScindi for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; 4127aec1d6eScindi nhp = topo_list_next(nhp)) { 4137aec1d6eScindi if (strcmp(nhp->th_name, name) == 0) { 4147aec1d6eScindi 4157aec1d6eScindi if (inst > nhp->th_range.tr_max || 4167aec1d6eScindi inst < nhp->th_range.tr_min) 4177aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, 4187aec1d6eScindi ETOPO_NODE_INVAL)); 4197aec1d6eScindi 4207aec1d6eScindi h = topo_node_hash(nhp, inst); 4217aec1d6eScindi if (nhp->th_nodearr[h] != NULL) 4227aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, 4237aec1d6eScindi ETOPO_NODE_BOUND)); 4247aec1d6eScindi else 4257aec1d6eScindi break; 4267aec1d6eScindi 4277aec1d6eScindi } 4287aec1d6eScindi } 4297aec1d6eScindi 4307aec1d6eScindi if (nhp == NULL) 4317aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_NOENT)); 4327aec1d6eScindi 4337aec1d6eScindi if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL) 4347aec1d6eScindi return (node_bind_seterror(mod, pnode, NULL, ETOPO_NOMEM)); 4357aec1d6eScindi 4367aec1d6eScindi (void) pthread_mutex_init(&node->tn_lock, NULL); 4377aec1d6eScindi 4387aec1d6eScindi node->tn_enum = mod; 4397aec1d6eScindi node->tn_hdl = mod->tm_hdl; 4407aec1d6eScindi node->tn_parent = pnode; 4417aec1d6eScindi node->tn_name = nhp->th_name; 4427aec1d6eScindi node->tn_instance = inst; 4437aec1d6eScindi node->tn_phash = nhp; 4447aec1d6eScindi node->tn_refs = 0; 4457aec1d6eScindi 4467aec1d6eScindi /* Ref count module that bound this node */ 4477aec1d6eScindi topo_mod_hold(mod); 4487aec1d6eScindi 4497aec1d6eScindi if (fmri == NULL) 4507aec1d6eScindi return (node_bind_seterror(mod, pnode, node, ETOPO_NODE_INVAL)); 4517aec1d6eScindi 452*0eb822a1Scindi if (topo_pgroup_create(node, &protocol_pgroup, &err) < 0) 4537aec1d6eScindi return (node_bind_seterror(mod, pnode, node, err)); 4547aec1d6eScindi 4557aec1d6eScindi if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, 456*0eb822a1Scindi TOPO_PROP_IMMUTABLE, fmri, &err) < 0) 4577aec1d6eScindi return (node_bind_seterror(mod, pnode, node, err)); 4587aec1d6eScindi 459*0eb822a1Scindi topo_dprintf(mod->tm_hdl, TOPO_DBG_MODSVC, 460*0eb822a1Scindi "node bound %s=%d\n", node->tn_name, node->tn_instance); 4617aec1d6eScindi 4627aec1d6eScindi node->tn_state |= TOPO_NODE_BOUND; 4637aec1d6eScindi 4647aec1d6eScindi topo_node_hold(node); 4657aec1d6eScindi nhp->th_nodearr[h] = node; 4667aec1d6eScindi ++pnode->tn_refs; 4677aec1d6eScindi topo_node_unlock(pnode); 4687aec1d6eScindi 469*0eb822a1Scindi if (topo_pgroup_create(node, &auth_pgroup, &err) == 0) { 470*0eb822a1Scindi (void) topo_prop_inherit(node, FM_FMRI_AUTHORITY, 471*0eb822a1Scindi FM_FMRI_AUTH_PRODUCT, &err); 472*0eb822a1Scindi (void) topo_prop_inherit(node, FM_FMRI_AUTHORITY, 473*0eb822a1Scindi FM_FMRI_AUTH_CHASSIS, &err); 474*0eb822a1Scindi (void) topo_prop_inherit(node, FM_FMRI_AUTHORITY, 475*0eb822a1Scindi FM_FMRI_AUTH_SERVER, &err); 4767aec1d6eScindi } 4777aec1d6eScindi 4787aec1d6eScindi return (node); 4797aec1d6eScindi } 4807aec1d6eScindi 4817aec1d6eScindi void 4827aec1d6eScindi topo_node_unbind(tnode_t *node) 4837aec1d6eScindi { 4847aec1d6eScindi if (node == NULL) 4857aec1d6eScindi return; 4867aec1d6eScindi 4877aec1d6eScindi topo_node_lock(node); 4887aec1d6eScindi if (!(node->tn_state & TOPO_NODE_BOUND)) { 4897aec1d6eScindi topo_node_unlock(node); 4907aec1d6eScindi return; 4917aec1d6eScindi } 4927aec1d6eScindi 4937aec1d6eScindi node->tn_state &= ~TOPO_NODE_BOUND; 4947aec1d6eScindi topo_node_unlock(node); 4957aec1d6eScindi 4967aec1d6eScindi topo_node_rele(node); 4977aec1d6eScindi } 4987aec1d6eScindi 4997aec1d6eScindi /*ARGSUSED*/ 5007aec1d6eScindi int 5017aec1d6eScindi topo_node_present(tnode_t *node) 5027aec1d6eScindi { 5037aec1d6eScindi return (0); 5047aec1d6eScindi } 5057aec1d6eScindi 5067aec1d6eScindi /*ARGSUSED*/ 5077aec1d6eScindi int 5087aec1d6eScindi topo_node_contains(tnode_t *er, tnode_t *ee) 5097aec1d6eScindi { 5107aec1d6eScindi return (0); 5117aec1d6eScindi } 5127aec1d6eScindi 5137aec1d6eScindi /*ARGSUSED*/ 5147aec1d6eScindi int 5157aec1d6eScindi topo_node_unusable(tnode_t *node) 5167aec1d6eScindi { 5177aec1d6eScindi return (0); 5187aec1d6eScindi } 519