fm: remove sparc topo maps
[unleashed.git] / usr / src / lib / fm / topo / modules / sun4v / chip / chip_sun4v.c
blobffcd6071ef214dea8deb3eb628b024c1eb8c4f51
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <strings.h>
30 #include <sys/types.h>
31 #include <fm/topo_mod.h>
32 #include <fm/topo_hc.h>
33 #include <sys/fm/protocol.h>
35 #include <unistd.h>
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <umem.h>
41 #include <cpu_mdesc.h>
45 * Enumerates the processing chips, or sockets, (as distinct from cores) in a
46 * system. For each chip found, the necessary nodes (one or more cores, and
47 * possibly a memory controller) are constructed underneath.
50 #define CHIP_VERSION TOPO_VERSION
51 #define CPU_NODE_NAME "cpu"
52 #define CHIP_NODE_NAME "chip"
54 extern topo_method_t pi_cpu_methods[];
56 /* Forward declaration */
57 static int chip_enum(topo_mod_t *, tnode_t *, const char *, topo_instance_t,
58 topo_instance_t, void *, void *);
59 static void chip_release(topo_mod_t *, tnode_t *);
61 static const topo_modops_t chip_ops =
62 { chip_enum, chip_release };
63 static const topo_modinfo_t chip_info =
64 { "chip", FM_FMRI_SCHEME_HC, CHIP_VERSION, &chip_ops };
67 static const topo_pgroup_info_t chip_auth_pgroup = {
68 FM_FMRI_AUTHORITY,
69 TOPO_STABILITY_PRIVATE,
70 TOPO_STABILITY_PRIVATE,
74 int
75 _topo_init(topo_mod_t *mod)
77 md_info_t *chip;
79 if (getenv("TOPOCHIPDBG"))
80 topo_mod_setdebug(mod);
81 topo_mod_dprintf(mod, "initializing chip enumerator\n");
83 if ((chip = topo_mod_zalloc(mod, sizeof (md_info_t))) == NULL)
84 return (-1);
86 if (cpu_mdesc_init(mod, chip) != 0) {
87 topo_mod_dprintf(mod, "failed to get cpus from the PRI/MD\n");
88 topo_mod_free(mod, chip, sizeof (md_info_t));
89 return (-1);
92 topo_mod_setspecific(mod, (void *)chip);
94 if (topo_mod_register(mod, &chip_info, TOPO_VERSION) != 0) {
95 topo_mod_dprintf(mod, "failed to register hc: "
96 "%s\n", topo_mod_errmsg(mod));
97 cpu_mdesc_fini(mod, chip);
98 topo_mod_free(mod, chip, sizeof (md_info_t));
99 return (-1);
102 topo_mod_dprintf(mod, "chip enumerator inited\n");
104 return (0);
107 void
108 _topo_fini(topo_mod_t *mod)
110 md_info_t *chip;
112 chip = (md_info_t *)topo_mod_getspecific(mod);
114 cpu_mdesc_fini(mod, chip);
116 topo_mod_free(mod, chip, sizeof (md_info_t));
118 topo_mod_unregister(mod);
121 static tnode_t *
122 chip_tnode_create(topo_mod_t *mod, tnode_t *parent,
123 const char *name, topo_instance_t i, char *serial,
124 nvlist_t *fru, char *label, void *priv)
126 int err;
127 nvlist_t *fmri;
128 tnode_t *ntn;
129 char *prod = NULL, *psn = NULL, *csn = NULL, *server = NULL;
130 nvlist_t *auth = NULL;
132 if (topo_mod_nvalloc(mod, &auth, NV_UNIQUE_NAME) == 0) {
133 if (topo_prop_get_string(parent, FM_FMRI_AUTHORITY,
134 FM_FMRI_AUTH_PRODUCT, &prod, &err) == 0) {
135 (void) nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT,
136 prod);
137 topo_mod_strfree(mod, prod);
139 if (topo_prop_get_string(parent, FM_FMRI_AUTHORITY,
140 FM_FMRI_AUTH_PRODUCT_SN, &psn, &err) == 0) {
141 (void) nvlist_add_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
142 psn);
143 topo_mod_strfree(mod, psn);
145 if (topo_prop_get_string(parent, FM_FMRI_AUTHORITY,
146 FM_FMRI_AUTH_SERVER, &server, &err) == 0) {
147 (void) nvlist_add_string(auth, FM_FMRI_AUTH_SERVER,
148 server);
149 topo_mod_strfree(mod, server);
151 if (topo_prop_get_string(parent, FM_FMRI_AUTHORITY,
152 FM_FMRI_AUTH_CHASSIS, &csn, &err) == 0) {
153 (void) nvlist_add_string(auth, FM_FMRI_AUTH_CHASSIS,
154 csn);
155 topo_mod_strfree(mod, csn);
160 fmri = topo_mod_hcfmri(mod, parent, FM_HC_SCHEME_VERSION, name, i,
161 NULL, auth, NULL, NULL, serial);
162 nvlist_free(auth);
163 if (fmri == NULL) {
164 topo_mod_dprintf(mod,
165 "Unable to make nvlist for %s bind: %s.\n",
166 name, topo_mod_errmsg(mod));
167 return (NULL);
170 ntn = topo_node_bind(mod, parent, name, i, fmri);
171 if (ntn == NULL) {
172 topo_mod_dprintf(mod,
173 "topo_node_bind (%s%d/%s%d) failed: %s\n",
174 topo_node_name(parent), topo_node_instance(parent),
175 name, i,
176 topo_strerror(topo_mod_errno(mod)));
177 nvlist_free(fmri);
178 return (NULL);
180 nvlist_free(fmri);
181 topo_node_setspecific(ntn, priv);
183 if (topo_pgroup_create(ntn, &chip_auth_pgroup, &err) == 0) {
184 (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
185 FM_FMRI_AUTH_PRODUCT, &err);
186 (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
187 FM_FMRI_AUTH_PRODUCT_SN, &err);
188 (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
189 FM_FMRI_AUTH_CHASSIS, &err);
190 (void) topo_prop_inherit(ntn, FM_FMRI_AUTHORITY,
191 FM_FMRI_AUTH_SERVER, &err);
194 /* Inherit the Label FRU fields from the parent */
195 (void) topo_node_label_set(ntn, label, &err);
196 (void) topo_node_fru_set(ntn, fru, 0, &err);
198 /* Register retire methods */
199 if (topo_method_register(mod, ntn, pi_cpu_methods) < 0)
200 topo_mod_dprintf(mod, "Unsable to register retire methods "
201 "for %s%d/%s%d: %s\n",
202 topo_node_name(parent), topo_node_instance(parent),
203 name, i, topo_mod_errmsg(mod));
205 return (ntn);
208 static nvlist_t *
209 cpu_fmri_create(topo_mod_t *mod, uint32_t cpuid, char *serial, uint8_t cpumask)
211 int err;
212 nvlist_t *fmri;
214 if (topo_mod_nvalloc(mod, &fmri, NV_UNIQUE_NAME) != 0)
215 return (NULL);
216 err = nvlist_add_uint8(fmri, FM_VERSION, FM_CPU_SCHEME_VERSION);
217 err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_CPU);
218 err |= nvlist_add_uint32(fmri, FM_FMRI_CPU_ID, cpuid);
219 err |= nvlist_add_uint8(fmri, FM_FMRI_CPU_MASK, cpumask);
220 if (serial != NULL)
221 err |= nvlist_add_string(fmri, FM_FMRI_CPU_SERIAL_ID, serial);
222 if (err != 0) {
223 nvlist_free(fmri);
224 (void) topo_mod_seterrno(mod, EMOD_FMRI_NVL);
225 return (NULL);
228 return (fmri);
231 /*ARGSUSED*/
232 static int
233 cpu_create(topo_mod_t *mod, tnode_t *rnode, const char *name, md_info_t *chip,
234 uint64_t serial)
236 int i;
237 int min = -1;
238 int max = -1;
239 int err;
240 int nerr = 0;
241 int pid;
242 char sbuf[32];
243 tnode_t *cnode;
244 nvlist_t *asru;
245 md_cpumap_t *mcmp;
247 topo_mod_dprintf(mod, "enumerating cpus\n");
250 * find the min/max id of cpus per this cmp and create a cpu range
252 for (i = 0, mcmp = chip->cpus; i < chip->ncpus; i++, mcmp++) {
253 if (mcmp->cpumap_serialno != serial)
254 continue;
255 if ((min < 0) || (mcmp->cpumap_pid < min))
256 min = mcmp->cpumap_pid;
257 if ((max < 0) || (mcmp->cpumap_pid > max))
258 max = mcmp->cpumap_pid;
260 if (min < 0 || max < 0) {
261 topo_mod_dprintf(mod, "Invalid cpu range(%d,%d)\n", min, max);
262 return (-1);
264 if (topo_node_range_create(mod, rnode, name, 0, max+1) < 0) {
265 topo_mod_dprintf(mod, "failed to create cpu range[0,%d]: %s\n",
266 max, topo_mod_errmsg(mod));
267 return (-1);
270 (void) snprintf(sbuf, sizeof (sbuf), "%llx", serial);
273 * Create the cpu[i] nodes of a given cmp i
275 for (i = 0, mcmp = chip->cpus; i < chip->ncpus; i++, mcmp++) {
277 if (mcmp->cpumap_serialno == 0 ||
278 mcmp->cpumap_serialno != serial) {
279 continue;
282 /* physical cpuid */
283 pid = mcmp->cpumap_pid;
284 cnode = chip_tnode_create(mod, rnode, name,
285 (topo_instance_t)pid, sbuf, NULL, NULL, NULL);
286 if (cnode == NULL) {
287 topo_mod_dprintf(mod,
288 "failed to create a cpu=%d node: %s\n",
289 pid, topo_mod_errmsg(mod));
290 nerr++;
291 continue;
294 if ((asru = cpu_fmri_create(mod, pid, sbuf, 0)) != NULL) {
295 (void) topo_node_asru_set(cnode, asru, 0, &err);
296 nvlist_free(asru);
297 } else {
298 nerr++;
302 if (nerr != 0)
303 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
305 return (0);
308 static int
309 dimm_instantiate(tnode_t *parent, const char *name, topo_mod_t *mod)
311 if (strcmp(name, CHIP) != 0) {
312 topo_mod_dprintf(mod,
313 "Currently only know how to enumerate %s components.\n",
314 CHIP);
315 return (0);
317 topo_mod_dprintf(mod,
318 "Calling dimm_enum\n");
319 if (topo_mod_enumerate(mod,
320 parent, DIMM, DIMM, 0, 0, NULL) != 0) {
321 return (topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM));
323 return (0);
326 static topo_mod_t *
327 dimm_enum_load(topo_mod_t *mp)
329 topo_mod_t *rp = NULL;
331 topo_mod_dprintf(mp, "dimm_enum_load: %s\n", CHIP);
332 if ((rp = topo_mod_load(mp, DIMM, TOPO_VERSION)) == NULL) {
333 topo_mod_dprintf(mp,
334 "%s enumerator could not load %s enum. (%d: %s)\n",
335 CHIP, DIMM, errno, strerror(errno));
337 topo_mod_dprintf(mp, "dimm_enum_load(EXIT): %s, rp=%p\n", CHIP, rp);
338 return (rp);
341 /*ARGSUSED*/
342 static int
343 chip_create(topo_mod_t *mod, tnode_t *rnode, const char *name,
344 topo_instance_t min, topo_instance_t max, md_info_t *chip)
346 int nerr = 0;
347 int err;
348 int i;
349 char sbuf[32];
350 tnode_t *cnode;
351 nvlist_t *fru = NULL;
352 char *label = NULL;
353 md_proc_t *procp;
355 topo_mod_dprintf(mod, "enumerating cmp chip\n");
356 if (min < 0 || max < 0 || min > max) {
357 topo_mod_dprintf(mod, "Invalid chip range(%d,%d)\n", min, max);
358 return (-1);
361 if (dimm_enum_load(mod) == NULL)
362 return (-1);
365 * Create the chip[i] nodes, one for each CMP chip uniquely identified
366 * by the serial number.
368 for (i = min; i <= max; i++) {
370 /* Skip the processors with no serial number */
371 if ((procp = cpu_find_proc(chip, i)) == NULL) {
372 continue;
374 if (procp->serialno == 0) {
375 continue;
378 (void) snprintf(sbuf, sizeof (sbuf), "%llx", procp->serialno);
379 topo_mod_dprintf(mod, "node chip[%d], sn=%s\n", i, sbuf);
381 cnode = chip_tnode_create(mod, rnode, name, (topo_instance_t)i,
382 sbuf, fru, label, NULL);
383 if (cnode == NULL) {
384 topo_mod_dprintf(mod, "failed to create a chip node: "
385 "%s\n", topo_mod_errmsg(mod));
386 nerr++;
387 continue;
390 /* Enumerate all cpu strands of this CMP chip */
391 err = cpu_create(mod, cnode, CPU_NODE_NAME, chip,
392 procp->serialno);
393 if (err != 0) {
394 nerr++;
397 /* Enumerate all DIMMs belonging to this chip */
398 if (dimm_instantiate(cnode, CHIP, mod) < 0) {
399 topo_mod_dprintf(mod, "Enumeration of dimm "
400 "failed %s\n", topo_mod_errmsg(mod));
401 return (-1);
405 if (nerr != 0)
406 (void) topo_mod_seterrno(mod, EMOD_PARTIAL_ENUM);
408 return (0);
411 /*ARGSUSED*/
412 static int
413 chip_enum(topo_mod_t *mod, tnode_t *rnode, const char *name,
414 topo_instance_t min, topo_instance_t max, void *arg, void *notused)
416 md_info_t *chip = (md_info_t *)arg;
418 if (strcmp(name, CHIP_NODE_NAME) == 0)
419 return (chip_create(mod, rnode, name, min, max, chip));
421 return (0);
424 /*ARGSUSED*/
425 static void
426 chip_release(topo_mod_t *mp, tnode_t *node)