1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <assert.h> 29 #include <pthread.h> 30 #include <strings.h> 31 #include <sys/fm/protocol.h> 32 33 #include <topo_alloc.h> 34 #include <topo_error.h> 35 #include <topo_method.h> 36 #include <topo_protocol.h> 37 #include <topo_subr.h> 38 39 #include <libtopo.h> 40 41 static int 42 topo_compute(tnode_t *node, nvlist_t *stub, const char *method, 43 topo_version_t version, nvlist_t *rsrc, nvlist_t **asru, int *err) 44 { 45 int rc; 46 char *scheme; 47 topo_hdl_t *thp = node->tn_hdl; 48 tnode_t *rnode; 49 50 /* 51 * First try the originating enumerator for 52 * a compute method. If none is supported, try the 53 * node's scheme-specific enumerator. 54 */ 55 if (topo_method_invoke(node, method, version, rsrc, asru, err) == 0) 56 return (0); 57 58 if (*err != ETOPO_METHOD_NOTSUP) 59 return (-1); 60 61 if ((rc = nvlist_lookup_string(stub, FM_FMRI_SCHEME, &scheme)) != 0) { 62 if (rc == ENOENT) { 63 *err = ETOPO_FMRI_MALFORM; 64 } else { 65 *err = ETOPO_FMRI_NVL; 66 } 67 return (-1); 68 } 69 70 if ((rnode = topo_hdl_root(thp, scheme)) == NULL) { 71 *err = ETOPO_METHOD_NOTSUP; 72 return (-1); 73 } 74 75 if (topo_method_invoke(rnode, method, version, rsrc, asru, err) != 0) 76 return (-1); 77 78 return (0); 79 } 80 81 int 82 topo_node_asru(tnode_t *node, nvlist_t **asru, nvlist_t *priv, int *err) 83 { 84 int rc; 85 nvlist_t *ap; 86 87 if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU, &ap, 88 err) != 0) 89 return (-1); 90 91 if (node->tn_fflags & TOPO_ASRU_COMPUTE) { 92 rc = topo_compute(node, ap, TOPO_METH_ASRU_COMPUTE, 93 TOPO_METH_ASRU_COMPUTE_VERSION, priv, asru, err); 94 nvlist_free(ap); 95 return (rc); 96 } else { 97 *asru = ap; 98 return (0); 99 } 100 } 101 102 int 103 topo_node_fru(tnode_t *node, nvlist_t **fru, nvlist_t *priv, int *err) 104 { 105 int rc; 106 nvlist_t *fp; 107 108 if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU, &fp, 109 err) != 0) 110 return (-1); 111 112 if (node->tn_fflags & TOPO_FRU_COMPUTE) { 113 rc = topo_compute(node, fp, TOPO_METH_FRU_COMPUTE, 114 TOPO_METH_FRU_COMPUTE_VERSION, priv, fru, err); 115 nvlist_free(fp); 116 return (rc); 117 } else { 118 *fru = fp; 119 return (0); 120 } 121 } 122 123 int 124 topo_node_resource(tnode_t *node, nvlist_t **resource, int *err) 125 { 126 127 return (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, 128 TOPO_PROP_RESOURCE, resource, err)); 129 } 130 131 int 132 topo_node_label(tnode_t *node, char **label, int *err) 133 { 134 135 return (topo_prop_get_string(node, TOPO_PGROUP_PROTOCOL, 136 TOPO_PROP_LABEL, label, err)); 137 } 138 139 int 140 topo_node_asru_set(tnode_t *node, nvlist_t *asru, int flag, int *err) 141 { 142 143 /* 144 * Inherit ASRU property from our parent if not specified 145 */ 146 if (asru == NULL) { 147 if (topo_prop_inherit(node, TOPO_PGROUP_PROTOCOL, 148 TOPO_PROP_ASRU, err) < 0) { 149 return (-1); 150 } 151 } else { 152 /* 153 * ASRU must be computed on the fly. asru will 154 * contain the scheme module to call for the 155 * computation 156 */ 157 if (flag & TOPO_ASRU_COMPUTE) 158 node->tn_fflags |= TOPO_ASRU_COMPUTE; 159 160 if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, 161 TOPO_PROP_ASRU, TOPO_PROP_IMMUTABLE, asru, err) < 0) 162 return (-1); 163 } 164 165 return (0); 166 } 167 168 int 169 topo_node_fru_set(tnode_t *node, nvlist_t *fru, int flag, int *err) 170 { 171 172 /* 173 * Inherit FRU property from our parent if * not specified 174 */ 175 if (fru == NULL) { 176 if (topo_prop_inherit(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU, 177 err) < 0) { 178 return (-1); 179 } 180 } else { 181 /* 182 * FRU must be computed on the fly 183 */ 184 if (flag & TOPO_FRU_COMPUTE) 185 node->tn_fflags |= TOPO_FRU_COMPUTE; 186 187 if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, 188 TOPO_PROP_FRU, TOPO_PROP_IMMUTABLE, fru, err) < 0) 189 return (-1); 190 } 191 192 return (0); 193 } 194 195 int 196 topo_node_label_set(tnode_t *node, char *label, int *err) 197 { 198 199 /* 200 * Inherit FRU property from our parent if * not specified 201 */ 202 if (label == NULL) { 203 if (topo_prop_inherit(node, TOPO_PGROUP_PROTOCOL, 204 TOPO_PROP_LABEL, err) < 0) { 205 return (-1); 206 } 207 } else { 208 if (topo_prop_set_string(node, TOPO_PGROUP_PROTOCOL, 209 TOPO_PROP_LABEL, TOPO_PROP_IMMUTABLE, label, err) < 0) 210 return (-1); 211 } 212 213 return (0); 214 } 215