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]
23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
29 #include <fm/topo_mod.h>
30 #include <fm/topo_hc.h>
31 #include <libdevinfo.h>
33 #include <sys/fm/protocol.h>
34 #include <sys/param.h>
35 #include <sys/systeminfo.h>
37 #include <sys/utsname.h>
38 #include <sys/systeminfo.h>
39 #include <fm/fmd_fmri.h>
40 #include <sys/types.h>
41 #include <sys/mdesc.h>
42 #include <sys/fm/ldom.h>
44 #include "cpuboard_topo.h"
48 * sun4v specific cpuboard enumerator
55 #define CPUBOARD_VERSION TOPO_VERSION
57 /* Until future PRI changes, make connection between cpuboard id and RC */
58 char *cpub_rcs
[] = { CPUBOARD0_RC
, CPUBOARD1_RC
, CPUBOARD2_RC
, CPUBOARD3_RC
};
60 static int cpuboard_enum(topo_mod_t
*, tnode_t
*, const char *, topo_instance_t
,
61 topo_instance_t
, void *, void *);
63 static const topo_modops_t cpuboard_ops
=
64 { cpuboard_enum
, NULL
};
66 const topo_modinfo_t cpuboard_info
=
67 {CPUBOARD
, FM_FMRI_SCHEME_HC
, CPUBOARD_VERSION
, &cpuboard_ops
};
69 static const topo_pgroup_info_t cpuboard_auth_pgroup
=
70 { FM_FMRI_AUTHORITY
, TOPO_STABILITY_PRIVATE
,
71 TOPO_STABILITY_PRIVATE
, 1 };
73 static topo_mod_t
*cpuboard_mod_hdl
= NULL
;
76 cpuboard_topo_alloc(size_t size
)
78 assert(cpuboard_mod_hdl
!= NULL
);
79 return (topo_mod_alloc(cpuboard_mod_hdl
, size
));
83 cpuboard_topo_free(void *data
, size_t size
)
85 assert(cpuboard_mod_hdl
!= NULL
);
86 topo_mod_free(cpuboard_mod_hdl
, data
, size
);
90 cpuboard_get_pri_info(topo_mod_t
*mod
, cpuboard_contents_t cpubs
[])
97 int ncomp
, num_nodes
, i
, len
;
99 char *sn
= NULL
, *pn
= NULL
;
104 int cpuboards_found
= 0;
106 lhp
= ldom_init(cpuboard_topo_alloc
, cpuboard_topo_free
);
108 topo_mod_dprintf(mod
, "ldom_init failed\n");
112 (void) sysinfo(SI_MACHINE
, isa
, MAXNAMELEN
);
113 if (strcmp(isa
, "sun4v") != 0) {
114 topo_mod_dprintf(mod
, "not sun4v architecture%s\n", isa
);
119 (void) ldom_get_type(lhp
, &type
);
120 if ((type
& LDOM_TYPE_CONTROL
) != 0) {
121 bufsize
= ldom_get_core_md(lhp
, &bufp
);
123 bufsize
= ldom_get_local_md(lhp
, &bufp
);
126 topo_mod_dprintf(mod
, "Failed to get pri/md, bufsize=%d\n",
131 topo_mod_dprintf(mod
, "pri/md bufsize=%d\n", bufsize
);
133 if ((mdp
= md_init_intern(bufp
, cpuboard_topo_alloc
,
134 cpuboard_topo_free
)) == NULL
||
135 (num_nodes
= md_node_count(mdp
)) < 1) {
136 topo_mod_dprintf(mod
, "md_init_intern error\n");
137 cpuboard_topo_free(bufp
, (size_t)bufsize
);
141 topo_mod_dprintf(mod
, "num_nodes=%d\n", num_nodes
);
143 if ((listp
= (mde_cookie_t
*)cpuboard_topo_alloc(
144 sizeof (mde_cookie_t
) * num_nodes
)) == NULL
) {
145 topo_mod_dprintf(mod
, "alloc listp error\n");
146 cpuboard_topo_free(bufp
, (size_t)bufsize
);
151 ncomp
= md_scan_dag(mdp
, MDE_INVAL_ELEM_COOKIE
,
152 md_find_name(mdp
, "component"),
153 md_find_name(mdp
, "fwd"), listp
);
154 topo_mod_dprintf(mod
, "ncomp=%d\n", ncomp
);
156 cpuboard_topo_free(listp
, sizeof (mde_cookie_t
) * num_nodes
);
157 cpuboard_topo_free(bufp
, (size_t)bufsize
);
162 for (i
= 0; i
< ncomp
; i
++) {
164 * PRI nodes are still named "cpu-board", but the canonical
165 * names are "cpuboard".
167 if (md_get_prop_str(mdp
, listp
[i
], "type", &pstr
) == 0 &&
168 pstr
!= NULL
&& strcmp(pstr
, "cpu-board") == 0) {
169 if (md_get_prop_val(mdp
, listp
[i
], "id", &id
) < 0) {
170 topo_mod_dprintf(mod
, "cpuboard_get_pri_info: "
171 "id md_get_prop_val() failed. (%d: %s)\n",
172 errno
, strerror(errno
));
175 if ((id
>= CPUBOARD_MAX
) || cpubs
[id
].present
) {
176 (void) topo_mod_seterrno(mod
, EMOD_NVL_INVAL
);
177 topo_mod_dprintf(mod
, "cpuboard_get_pri_info: "
178 "id %llx out of range. (%d: %s)\n",
179 id
, errno
, strerror(errno
));
182 cpubs
[id
].present
= 1;
185 topo_mod_dprintf(mod
, "got cpu-board: %llx\n", id
);
189 (void) md_get_prop_str(mdp
, listp
[i
],
190 "serial_number", &sn
);
191 cpubs
[id
].sn
= topo_mod_strdup(mod
, sn
);
193 (void) md_get_prop_str(mdp
, listp
[i
],
196 (void) md_get_prop_str(mdp
, listp
[i
],
198 len
= (pn
? strlen(pn
) : 0) + (dn
? strlen(dn
) : 0) + 1;
199 pstr
= cpuboard_topo_alloc(len
);
200 (void) snprintf(pstr
, len
, "%s%s",
201 pn
? pn
: "", dn
? dn
: "");
202 cpubs
[id
].pn
= topo_mod_strdup(mod
, pstr
);
203 cpuboard_topo_free(pstr
, len
);
206 cpuboard_topo_free(listp
, sizeof (mde_cookie_t
) * num_nodes
);
207 cpuboard_topo_free(bufp
, (size_t)bufsize
);
211 return (cpuboards_found
);
216 _topo_init(topo_mod_t
*mod
, topo_version_t version
)
219 * Turn on module debugging output
221 if (getenv("TOPOCPUBOARDDBG") != NULL
) {
222 topo_mod_setdebug(mod
);
224 topo_mod_dprintf(mod
, "initializing cpuboard enumerator\n");
226 if (topo_mod_register(mod
, &cpuboard_info
, TOPO_VERSION
) < 0) {
227 topo_mod_dprintf(mod
, "cpuboard registration failed: %s\n",
228 topo_mod_errmsg(mod
));
229 return; /* mod errno already set */
231 topo_mod_dprintf(mod
, "cpuboard enumr initd\n");
235 _topo_fini(topo_mod_t
*mod
)
237 topo_mod_unregister(mod
);
241 cpuboard_tnode_create(topo_mod_t
*mod
, tnode_t
*parent
,
242 const char *name
, topo_instance_t i
, void *priv
, cpuboard_contents_t
*cpubc
)
247 nvlist_t
*auth
= topo_mod_auth(mod
, parent
);
249 fmri
= topo_mod_hcfmri(mod
, parent
, FM_HC_SCHEME_VERSION
, name
, i
,
250 NULL
, auth
, cpubc
->pn
, NULL
, cpubc
->sn
);
254 topo_mod_dprintf(mod
,
255 "Unable to make nvlist for %s bind: %s.\n",
256 name
, topo_mod_errmsg(mod
));
260 ntn
= topo_node_bind(mod
, parent
, name
, i
, fmri
);
262 topo_mod_dprintf(mod
,
263 "topo_node_bind (%s%d/%s%d) failed: %s\n",
264 topo_node_name(parent
), topo_node_instance(parent
),
266 topo_strerror(topo_mod_errno(mod
)));
270 topo_mod_dprintf(mod
,
271 "cpuboard_tnode_create: topo_node_bind (%s%d/%s%d) created!\n",
272 topo_node_name(parent
), topo_node_instance(parent
), name
, i
);
274 topo_node_setspecific(ntn
, priv
);
276 if (topo_pgroup_create(ntn
, &cpuboard_auth_pgroup
, &err
) == 0) {
277 (void) topo_prop_inherit(ntn
, FM_FMRI_AUTHORITY
,
278 FM_FMRI_AUTH_PRODUCT
, &err
);
279 (void) topo_prop_inherit(ntn
, FM_FMRI_AUTHORITY
,
280 FM_FMRI_AUTH_PRODUCT_SN
, &err
);
281 (void) topo_prop_inherit(ntn
, FM_FMRI_AUTHORITY
,
282 FM_FMRI_AUTH_CHASSIS
, &err
);
283 (void) topo_prop_inherit(ntn
, FM_FMRI_AUTHORITY
,
284 FM_FMRI_AUTH_SERVER
, &err
);
291 cpuboard_fru_set(topo_mod_t
*mp
, tnode_t
*tn
)
296 if (topo_node_resource(tn
, &fmri
, &err
) < 0 ||
298 topo_mod_dprintf(mp
, "FRU_fmri_set error: %s\n",
299 topo_strerror(topo_mod_errno(mp
)));
300 return (topo_mod_seterrno(mp
, err
));
302 e
= topo_node_fru_set(tn
, fmri
, 0, &err
);
305 return (topo_mod_seterrno(mp
, err
));
310 cpuboard_label_set(topo_mod_t
*mod
, tnode_t
*parent
, tnode_t
*node
,
315 const char *cpuboard_label
= "/CPU";
318 if (topo_node_label(parent
, &plabel
, &err
) != 0 ||
323 len
= strlen(plabel
) + strlen(cpuboard_label
) + 2;
324 label
= topo_mod_alloc(mod
, len
);
325 (void) snprintf(label
, len
, "%s%s%d", plabel
, cpuboard_label
, n
);
326 topo_mod_strfree(mod
, plabel
);
329 if (topo_prop_set_string(node
, TOPO_PGROUP_PROTOCOL
,
330 TOPO_PROP_LABEL
, TOPO_PROP_IMMUTABLE
, label
,
332 topo_mod_strfree(mod
, label
);
333 return (topo_mod_seterrno(mod
, err
));
336 topo_mod_free(mod
, label
, len
);
343 cpuboard_declare(tnode_t
*parent
, const char *name
, topo_instance_t i
,
344 void *priv
, topo_mod_t
*mod
, cpuboard_contents_t
*cpubc
)
347 nvlist_t
*fmri
= NULL
;
350 if ((ntn
= cpuboard_tnode_create(mod
, parent
, name
, i
, priv
,
352 topo_mod_dprintf(mod
, "%s ntn = NULL\n", name
);
356 (void) cpuboard_fru_set(mod
, ntn
);
358 (void) cpuboard_label_set(mod
, parent
, ntn
, i
);
360 /* set ASRU to resource fmri */
361 if (topo_prop_get_fmri(ntn
, TOPO_PGROUP_PROTOCOL
,
362 TOPO_PROP_RESOURCE
, &fmri
, &err
) == 0)
363 (void) topo_node_asru_set(ntn
, fmri
, 0, &err
);
370 chip_instantiate(tnode_t
*parent
, const char *name
, topo_mod_t
*mod
,
371 topo_instance_t inst
)
373 if (strcmp(name
, CPUBOARD
) != 0) {
374 topo_mod_dprintf(mod
,
375 "Currently only know how to enumerate %s components.\n",
379 topo_mod_dprintf(mod
,
380 "Calling chip_enum for inst: %lx\n", inst
);
381 if (topo_mod_enumerate(mod
,
382 parent
, CHIP
, CHIP
, inst
, inst
, NULL
) != 0) {
383 return (topo_mod_seterrno(mod
, EMOD_PARTIAL_ENUM
));
389 chip_enum_load(topo_mod_t
*mp
)
391 topo_mod_t
*rp
= NULL
;
393 topo_mod_dprintf(mp
, "chip_enum_load: %s\n", CPUBOARD
);
394 if ((rp
= topo_mod_load(mp
, CHIP
, TOPO_VERSION
)) == NULL
) {
396 "%s enumerator could not load %s enum. (%d: %s)\n",
397 CPUBOARD
, CHIP
, errno
, strerror(errno
));
399 topo_mod_dprintf(mp
, "chip_enum_load(EXIT): %s, rp=%p\n", CPUBOARD
, rp
);
404 cpuboard_findrc(topo_mod_t
*mod
, uint64_t id
)
409 if ((devtree
= topo_mod_devinfo(mod
)) == DI_NODE_NIL
) {
410 topo_mod_dprintf(mod
, "devinfo init failed.");
413 dnode
= di_drv_first_node(CPUBOARD_PX_DRV
, devtree
);
414 while (dnode
!= DI_NODE_NIL
) {
417 if ((path
= di_devfs_path(dnode
)) == NULL
) {
418 topo_mod_dprintf(mod
, "cpuboard_findrc: "
419 "NULL di_devfs_path.\n");
420 (void) topo_mod_seterrno(mod
, ETOPO_PROP_NOENT
);
423 topo_mod_dprintf(mod
, "cpuboard_findrc: "
424 "got px %d, node named: %s, path: %s\n",
425 di_instance(dnode
), di_node_name(dnode
), path
);
427 if (strcmp(cpub_rcs
[id
], path
) == 0) {
428 di_devfs_path_free(path
);
432 di_devfs_path_free(path
);
434 dnode
= di_drv_next_node(dnode
);
440 cpuboard_free_pri_info(topo_mod_t
*mod
, cpuboard_contents_t cpuboard_list
[],
441 topo_instance_t min
, topo_instance_t max
)
445 for (i
= min
; i
<= max
; i
++) {
446 if (cpuboard_list
[i
].present
== 0)
448 if (cpuboard_list
[i
].sn
!= NULL
)
449 topo_mod_strfree(mod
, cpuboard_list
[i
].sn
);
450 if (cpuboard_list
[i
].pn
!= NULL
)
451 topo_mod_strfree(mod
, cpuboard_list
[i
].pn
);
457 cpuboard_enum(topo_mod_t
*mod
, tnode_t
*parent
, const char *name
,
458 topo_instance_t min
, topo_instance_t max
, void *arg
, void *notused
)
461 topo_instance_t i
= 0;
462 cpuboard_contents_t cpuboard_list
[CPUBOARD_MAX
];
464 if (strcmp(name
, CPUBOARD
) != 0) {
465 topo_mod_dprintf(mod
,
466 "Currently only know how to enumerate %s components.\n",
470 /* Make sure we don't exceed CPUBOARD_MAX */
471 if (max
>= CPUBOARD_MAX
) {
475 bzero(cpuboard_list
, sizeof (cpuboard_list
));
477 /* Scan PRI for cpu-boards. */
478 cpuboard_mod_hdl
= mod
;
479 if (cpuboard_get_pri_info(mod
, cpuboard_list
) == 0) {
480 int cpuboards_found
= 0;
482 * if no PRI available (i.e. not in Control Domain),
483 * use px driver to determine cpuboard presence.
484 * NOTE: with this approach there will be no
485 * identity information - no SN nor PN.
487 bzero(cpuboard_list
, sizeof (cpuboard_list
));
488 for (i
= min
; i
<= max
; i
++) {
489 if (cpuboard_findrc(mod
, i
) != NULL
) {
490 cpuboard_list
[i
].present
= 1;
494 if (cpuboards_found
== 0) {
495 topo_mod_dprintf(mod
, "No cpuboards found.\n");
500 if (chip_enum_load(mod
) == NULL
) {
501 cpuboard_free_pri_info(mod
, cpuboard_list
, min
, max
);
505 for (i
= min
; i
<= max
; i
++) {
506 if (cpuboard_list
[i
].present
== 0)
509 cpuboardn
= cpuboard_declare(parent
, name
, i
,
510 NULL
, mod
, &cpuboard_list
[i
]);
511 if (cpuboardn
== NULL
) {
512 topo_mod_dprintf(mod
,
513 "Enumeration of cpuboard failed: %s\n",
514 topo_strerror(topo_mod_errno(mod
)));
515 cpuboard_free_pri_info(mod
, cpuboard_list
, min
, max
);
516 return (-1); /* mod_errno already set */
518 if (topo_node_range_create(mod
, cpuboardn
, CHIP
, 0,
520 topo_node_unbind(cpuboardn
);
521 topo_mod_dprintf(mod
, "topo_node_range_create CHIP "
522 "failed: %s\n", topo_strerror(topo_mod_errno(mod
)));
523 cpuboard_free_pri_info(mod
, cpuboard_list
, min
, max
);
524 return (-1); /* mod_errno already set */
526 if (chip_instantiate(cpuboardn
, CPUBOARD
, mod
, i
) < 0) {
527 topo_mod_dprintf(mod
, "Enumeration of chip "
529 topo_strerror(topo_mod_errno(mod
)));
530 cpuboard_free_pri_info(mod
, cpuboard_list
, min
, max
);
533 if (topo_node_range_create(mod
, cpuboardn
, HOSTBRIDGE
, 0,
534 HOSTBRIDGE_MAX
) < 0) {
535 topo_node_unbind(cpuboardn
);
536 topo_mod_dprintf(mod
, "topo_node_range_create: "
537 "HOSTBRIDGE failed: %s\n",
538 topo_strerror(topo_mod_errno(mod
)));
539 cpuboard_free_pri_info(mod
, cpuboard_list
, min
, max
);
542 if (cpuboard_hb_enum(mod
, cpuboard_findrc(mod
, i
), cpub_rcs
[i
],
544 topo_node_unbind(cpuboardn
);
545 topo_mod_dprintf(mod
, "cpuboard_hb_enum: "
547 topo_strerror(topo_mod_errno(mod
)));
548 cpuboard_free_pri_info(mod
, cpuboard_list
, min
, max
);
552 cpuboard_free_pri_info(mod
, cpuboard_list
, min
, max
);