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