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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright (c) 2017, Joyent, Inc.
36 #include <libnvpair.h>
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <sys/fm/protocol.h>
40 #include <fm/libtopo.h>
41 #include <fm/topo_mod.h>
46 #define BAY_PRESENT_LED_MASK 0x01
49 * The largest possible SDR ID length is 2^5+1
53 #define TOPO_METH_IPMI_PLATFORM_MESSAGE_VERSION 0
54 #define TOPO_METH_IPMI_READING_VERSION 0
55 #define TOPO_METH_IPMI_STATE_VERSION 0
56 #define TOPO_METH_IPMI_MODE_VERSION 0
57 #define TOPO_METH_X4500_MODE_VERSION 0
58 #define TOPO_METH_BAY_LOCATE_VERSION 0
59 #define TOPO_METH_BAY_MODE_VERSION 0
60 #define TOPO_METH_CHASSIS_SERVICE_VERSION 0
61 #define TOPO_METH_IPMI_ENTITY_VERSION 0
62 #define TOPO_METH_DIMM_IPMI_ENTITY_VERSION 0
63 #define TOPO_METH_CHASSIS_IDENT_VERSION 0
65 static int fac_prov_ipmi_enum(topo_mod_t
*, tnode_t
*, const char *,
66 topo_instance_t
, topo_instance_t
, void *, void *);
69 * IPMI facility provider methods
71 static int ipmi_sensor_enum(topo_mod_t
*, tnode_t
*, topo_version_t
,
72 nvlist_t
*, nvlist_t
**);
73 static int ipmi_entity(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
75 static int dimm_ipmi_entity(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
77 static int cs_ipmi_entity(topo_mod_t
*, tnode_t
*, topo_version_t
, nvlist_t
*,
79 static int ipmi_platform_message(topo_mod_t
*, tnode_t
*, topo_version_t
,
80 nvlist_t
*, nvlist_t
**);
81 static int ipmi_sensor_reading(topo_mod_t
*, tnode_t
*, topo_version_t
,
82 nvlist_t
*, nvlist_t
**);
83 static int ipmi_sensor_state(topo_mod_t
*, tnode_t
*, topo_version_t
,
84 nvlist_t
*, nvlist_t
**);
85 static int ipmi_indicator_mode(topo_mod_t
*, tnode_t
*, topo_version_t
,
86 nvlist_t
*, nvlist_t
**);
87 static int bay_locate_mode(topo_mod_t
*, tnode_t
*, topo_version_t
,
88 nvlist_t
*, nvlist_t
**);
89 static int x4500_present_mode(topo_mod_t
*, tnode_t
*, topo_version_t
,
90 nvlist_t
*, nvlist_t
**);
91 static int bay_indicator_mode(topo_mod_t
*, tnode_t
*, topo_version_t
,
92 nvlist_t
*, nvlist_t
**);
93 static int chassis_service_mode(topo_mod_t
*, tnode_t
*, topo_version_t
,
94 nvlist_t
*, nvlist_t
**);
95 static int chassis_ident_mode(topo_mod_t
*, tnode_t
*, topo_version_t
,
96 nvlist_t
*, nvlist_t
**);
98 const topo_modops_t ipmi_ops
= { fac_prov_ipmi_enum
, NULL
};
100 const topo_modinfo_t ipmi_info
=
101 { "IPMI facility provider", FM_FMRI_SCHEME_HC
, TOPO_VERSION
,
104 static const topo_method_t ipmi_node_methods
[] = {
105 { TOPO_METH_FAC_ENUM
, TOPO_METH_FAC_ENUM_DESC
, 0,
106 TOPO_STABILITY_INTERNAL
, ipmi_sensor_enum
},
107 { TOPO_METH_IPMI_ENTITY
, TOPO_PROP_METH_DESC
,
108 TOPO_METH_IPMI_ENTITY_VERSION
,
109 TOPO_STABILITY_INTERNAL
, ipmi_entity
},
110 { "dimm_ipmi_entity", TOPO_PROP_METH_DESC
,
111 TOPO_METH_DIMM_IPMI_ENTITY_VERSION
,
112 TOPO_STABILITY_INTERNAL
, dimm_ipmi_entity
},
113 { "cs_ipmi_entity", TOPO_PROP_METH_DESC
,
114 TOPO_METH_DIMM_IPMI_ENTITY_VERSION
,
115 TOPO_STABILITY_INTERNAL
, cs_ipmi_entity
},
119 static const topo_method_t ipmi_fac_methods
[] = {
120 { "ipmi_platform_message", TOPO_PROP_METH_DESC
,
121 TOPO_METH_IPMI_PLATFORM_MESSAGE_VERSION
,
122 TOPO_STABILITY_INTERNAL
, ipmi_platform_message
},
123 { "ipmi_sensor_reading", TOPO_PROP_METH_DESC
,
124 TOPO_METH_IPMI_READING_VERSION
,
125 TOPO_STABILITY_INTERNAL
, ipmi_sensor_reading
},
126 { "ipmi_sensor_state", TOPO_PROP_METH_DESC
,
127 TOPO_METH_IPMI_STATE_VERSION
,
128 TOPO_STABILITY_INTERNAL
, ipmi_sensor_state
},
129 { "ipmi_indicator_mode", TOPO_PROP_METH_DESC
,
130 TOPO_METH_IPMI_MODE_VERSION
,
131 TOPO_STABILITY_INTERNAL
, ipmi_indicator_mode
},
132 { "bay_locate_mode", TOPO_PROP_METH_DESC
,
133 TOPO_METH_BAY_LOCATE_VERSION
,
134 TOPO_STABILITY_INTERNAL
, bay_locate_mode
},
135 { "bay_indicator_mode", TOPO_PROP_METH_DESC
,
136 TOPO_METH_BAY_MODE_VERSION
,
137 TOPO_STABILITY_INTERNAL
, bay_indicator_mode
},
138 { "chassis_service_mode", TOPO_PROP_METH_DESC
,
139 TOPO_METH_CHASSIS_SERVICE_VERSION
,
140 TOPO_STABILITY_INTERNAL
, chassis_service_mode
},
141 { "chassis_ident_mode", TOPO_PROP_METH_DESC
,
142 TOPO_METH_CHASSIS_SERVICE_VERSION
,
143 TOPO_STABILITY_INTERNAL
, chassis_ident_mode
},
144 { "x4500_present_mode", TOPO_PROP_METH_DESC
,
145 TOPO_METH_CHASSIS_SERVICE_VERSION
,
146 TOPO_STABILITY_INTERNAL
, x4500_present_mode
},
147 { TOPO_METH_IPMI_ENTITY
, TOPO_PROP_METH_DESC
,
148 TOPO_METH_IPMI_ENTITY_VERSION
,
149 TOPO_STABILITY_INTERNAL
, ipmi_entity
},
150 { "dimm_ipmi_entity", TOPO_PROP_METH_DESC
,
151 TOPO_METH_DIMM_IPMI_ENTITY_VERSION
,
152 TOPO_STABILITY_INTERNAL
, dimm_ipmi_entity
},
153 { "cs_ipmi_entity", TOPO_PROP_METH_DESC
,
154 TOPO_METH_DIMM_IPMI_ENTITY_VERSION
,
155 TOPO_STABILITY_INTERNAL
, dimm_ipmi_entity
},
169 char sd_entity_ref
[MAX_ID_LEN
];
178 _topo_init(topo_mod_t
*mod
, topo_version_t version
)
180 if (getenv("TOPOFACIPMIDEBUG") != NULL
)
181 topo_mod_setdebug(mod
);
183 return (topo_mod_register(mod
, &ipmi_info
, TOPO_VERSION
));
187 _topo_fini(topo_mod_t
*mod
)
189 topo_mod_unregister(mod
);
193 strarr_free(topo_mod_t
*mod
, char **arr
, uint_t nelems
)
195 for (int i
= 0; i
< nelems
; i
++)
196 topo_mod_strfree(mod
, arr
[i
]);
197 topo_mod_free(mod
, arr
, (nelems
* sizeof (char *)));
201 * Some platforms (most notably G1/2N) use the 'platform event message' command
202 * to manipulate disk fault LEDs over IPMI, but uses the standard sensor
203 * reading to read the value. This method implements this alternative
204 * interface for these platforms.
208 ipmi_platform_message(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
209 nvlist_t
*in
, nvlist_t
**out
)
212 ipmi_sdr_compact_sensor_t
*csp
;
216 nvlist_t
*pargs
, *nvl
;
217 ipmi_platform_event_message_t pem
;
218 ipmi_sensor_reading_t
*reading
;
220 if (vers
> TOPO_METH_IPMI_PLATFORM_MESSAGE_VERSION
)
221 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
224 * Get an IPMI handle and then lookup the generic device locator sensor
225 * data record referenced by the entity_ref prop val
227 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
228 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
232 if (topo_prop_get_string(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
233 &entity_ref
, &err
) != 0) {
234 topo_mod_dprintf(mod
, "Failed to lookup entity_ref property "
235 "(%s)", topo_strerror(err
));
236 topo_mod_ipmi_rele(mod
);
240 if ((csp
= ipmi_sdr_lookup_compact_sensor(hdl
, entity_ref
)) == NULL
) {
241 topo_mod_dprintf(mod
, "Failed to lookup SDR for %s (%s)\n",
242 entity_ref
, ipmi_errmsg(hdl
));
243 topo_mod_strfree(mod
, entity_ref
);
244 topo_mod_ipmi_rele(mod
);
249 * Now look for a private argument list to figure out whether we're
250 * doing a get or a set operation, and then do it.
252 if ((nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &pargs
) == 0) &&
253 nvlist_exists(pargs
, TOPO_PROP_VAL_VAL
)) {
257 if ((ret
= nvlist_lookup_uint32(pargs
, TOPO_PROP_VAL_VAL
,
259 topo_mod_dprintf(mod
, "Failed to lookup %s nvpair "
260 "(%s)\n", TOPO_PROP_VAL_VAL
, strerror(ret
));
261 topo_mod_strfree(mod
, entity_ref
);
262 (void) topo_mod_seterrno(mod
, EMOD_NVL_INVAL
);
263 topo_mod_ipmi_rele(mod
);
267 if (mode
!= TOPO_LED_STATE_OFF
&&
268 mode
!= TOPO_LED_STATE_ON
) {
269 topo_mod_dprintf(mod
, "Invalid property value: %d\n",
271 topo_mod_strfree(mod
, entity_ref
);
272 (void) topo_mod_seterrno(mod
, EMOD_NVL_INVAL
);
273 topo_mod_ipmi_rele(mod
);
277 pem
.ipem_sensor_type
= csp
->is_cs_type
;
278 pem
.ipem_sensor_num
= csp
->is_cs_number
;
279 pem
.ipem_event_type
= csp
->is_cs_reading_type
;
282 * The spec states that any values between 0x20 and 0x29 are
283 * legitimate for "system software". However, some versions of
284 * Sun's ILOM rejects messages over /dev/ipmi0 with a generator
285 * of 0x20, so we use 0x21 instead.
287 pem
.ipem_generator
= 0x21;
288 pem
.ipem_event_dir
= 0;
290 if (mode
== TOPO_LED_STATE_ON
)
291 pem
.ipem_event_data
[0] = 1;
293 pem
.ipem_event_data
[0] = 0;
294 pem
.ipem_event_data
[1] = 0xff;
295 pem
.ipem_event_data
[2] = 0xff;
297 if (ipmi_event_platform_message(hdl
, &pem
) < 0) {
298 topo_mod_dprintf(mod
, "Failed to set LED mode for %s "
299 "(%s)\n", entity_ref
, ipmi_errmsg(hdl
));
300 topo_mod_strfree(mod
, entity_ref
);
301 topo_mod_ipmi_rele(mod
);
308 if ((reading
= ipmi_get_sensor_reading(hdl
, csp
->is_cs_number
))
310 topo_mod_dprintf(mod
, "Failed to get sensor reading "
311 "for sensor %s: %s\n", entity_ref
,
313 topo_mod_strfree(mod
, entity_ref
);
314 topo_mod_ipmi_rele(mod
);
318 if (reading
->isr_state
&
319 TOPO_SENSOR_STATE_GENERIC_STATE_ASSERTED
)
320 mode
= TOPO_LED_STATE_ON
;
322 mode
= TOPO_LED_STATE_OFF
;
324 topo_mod_strfree(mod
, entity_ref
);
326 topo_mod_ipmi_rele(mod
);
328 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
329 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, TOPO_LED_MODE
) != 0 ||
330 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
331 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, mode
) != 0) {
332 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
334 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
343 ipmi_sensor_state(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
344 nvlist_t
*in
, nvlist_t
**out
)
348 ipmi_sdr_t
*sdr
= NULL
;
349 ipmi_sensor_reading_t
*reading
;
353 ipmi_sdr_full_sensor_t
*fsensor
;
354 ipmi_sdr_compact_sensor_t
*csensor
;
356 boolean_t found_sdr
= B_FALSE
;
358 if (vers
> TOPO_METH_IPMI_STATE_VERSION
)
359 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
361 if (topo_prop_get_string_array(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
362 &entity_refs
, &nelems
, &err
) != 0) {
363 topo_mod_dprintf(mod
, "%s: Failed to lookup entity_ref "
364 "property (%s)", __func__
, topo_strerror(err
));
365 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
368 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
369 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
370 strarr_free(mod
, entity_refs
, nelems
);
374 for (i
= 0; i
< nelems
; i
++) {
375 if ((sdr
= ipmi_sdr_lookup(hdl
, entity_refs
[i
])) != NULL
) {
379 topo_mod_dprintf(mod
, "Failed to lookup SDR for %s "
380 "(%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
384 strarr_free(mod
, entity_refs
, nelems
);
385 topo_mod_ipmi_rele(mod
);
389 switch (sdr
->is_type
) {
390 case IPMI_SDR_TYPE_FULL_SENSOR
:
391 fsensor
= (ipmi_sdr_full_sensor_t
*)sdr
->is_record
;
392 sensor_num
= fsensor
->is_fs_number
;
394 case IPMI_SDR_TYPE_COMPACT_SENSOR
:
395 csensor
= (ipmi_sdr_compact_sensor_t
*)sdr
->is_record
;
396 sensor_num
= csensor
->is_cs_number
;
399 topo_mod_dprintf(mod
, "%s does not refer to a full or "
400 "compact SDR\n", entity_refs
[i
]);
401 topo_mod_ipmi_rele(mod
);
402 strarr_free(mod
, entity_refs
, nelems
);
405 if ((reading
= ipmi_get_sensor_reading(hdl
, sensor_num
))
407 topo_mod_dprintf(mod
, "Failed to get sensor reading for sensor "
408 "%s, sensor_num=%d (%s)\n", entity_refs
[i
], sensor_num
,
410 strarr_free(mod
, entity_refs
, nelems
);
411 topo_mod_ipmi_rele(mod
);
414 strarr_free(mod
, entity_refs
, nelems
);
415 topo_mod_ipmi_rele(mod
);
417 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
418 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
,
419 TOPO_SENSOR_STATE
) != 0 ||
420 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
421 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, reading
->isr_state
)
423 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
425 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
434 ipmi_sensor_reading(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
435 nvlist_t
*in
, nvlist_t
**out
)
437 char **entity_refs
, reading_str
[BUFSZ
];
440 ipmi_sdr_full_sensor_t
*sensor
;
441 ipmi_sensor_reading_t
*reading
;
445 boolean_t found_sdr
= B_FALSE
;
447 if (vers
> TOPO_METH_IPMI_READING_VERSION
)
448 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
450 if (topo_prop_get_string_array(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
451 &entity_refs
, &nelems
, &err
) != 0) {
452 topo_mod_dprintf(mod
, "Failed to lookup entity_ref property "
453 "(%s)", topo_strerror(err
));
454 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
457 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
458 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
459 strarr_free(mod
, entity_refs
, nelems
);
463 for (i
= 0; i
< nelems
; i
++) {
464 if ((sensor
= ipmi_sdr_lookup_full_sensor(hdl
, entity_refs
[i
]))
469 topo_mod_dprintf(mod
, "Failed to lookup SDR for %s "
470 "(%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
474 strarr_free(mod
, entity_refs
, nelems
);
475 topo_mod_ipmi_rele(mod
);
479 if ((reading
= ipmi_get_sensor_reading(hdl
, sensor
->is_fs_number
))
481 topo_mod_dprintf(mod
, "Failed to get sensor reading for sensor "
482 "%s, sensor_num=%d (%s)\n", entity_refs
[i
],
483 sensor
->is_fs_number
, ipmi_errmsg(hdl
));
484 strarr_free(mod
, entity_refs
, nelems
);
485 topo_mod_ipmi_rele(mod
);
488 topo_mod_ipmi_rele(mod
);
490 if (ipmi_sdr_conv_reading(sensor
, reading
->isr_reading
, &conv_reading
)
492 topo_mod_dprintf(mod
, "Failed to convert sensor reading for "
493 "sensor %s (%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
494 strarr_free(mod
, entity_refs
, nelems
);
497 strarr_free(mod
, entity_refs
, nelems
);
499 (void) snprintf(reading_str
, BUFSZ
, "%f", conv_reading
);
500 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
501 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
,
502 TOPO_SENSOR_READING
) != 0 ||
503 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_DOUBLE
) != 0 ||
504 nvlist_add_double(nvl
, TOPO_PROP_VAL_VAL
, conv_reading
) != 0) {
505 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
507 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
515 ipmi_indicator_mode(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
516 nvlist_t
*in
, nvlist_t
**out
)
520 ipmi_sdr_generic_locator_t
*gdl
= NULL
;
525 nvlist_t
*pargs
, *nvl
;
526 boolean_t found_sdr
= B_FALSE
;
528 if (vers
> TOPO_METH_IPMI_MODE_VERSION
)
529 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
532 * Get an IPMI handle and then lookup the generic device locator sensor
533 * data record referenced by the entity_ref prop val
535 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
536 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
540 if (topo_prop_get_string_array(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
541 &entity_refs
, &nelems
, &err
) != 0) {
542 topo_mod_dprintf(mod
, "Failed to lookup entity_ref property "
543 "(%s)", topo_strerror(err
));
544 topo_mod_ipmi_rele(mod
);
545 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
548 for (i
= 0; i
< nelems
; i
++) {
549 if ((gdl
= ipmi_sdr_lookup_generic(hdl
, entity_refs
[i
]))
554 topo_mod_dprintf(mod
, "Failed to lookup SDR for %s "
555 "(%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
559 strarr_free(mod
, entity_refs
, nelems
);
560 topo_mod_ipmi_rele(mod
);
565 * Now look for a private argument list to figure out whether we're
566 * doing a get or a set operation, and then do it.
568 if ((nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &pargs
) == 0) &&
569 nvlist_exists(pargs
, TOPO_PROP_VAL_VAL
)) {
573 if ((ret
= nvlist_lookup_uint32(pargs
, TOPO_PROP_VAL_VAL
,
575 topo_mod_dprintf(mod
, "Failed to lookup %s nvpair "
576 "(%s)\n", TOPO_PROP_VAL_VAL
, strerror(ret
));
577 strarr_free(mod
, entity_refs
, nelems
);
578 topo_mod_ipmi_rele(mod
);
579 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
581 if (mode_in
!= TOPO_LED_STATE_OFF
&&
582 mode_in
!= TOPO_LED_STATE_ON
) {
583 topo_mod_dprintf(mod
, "Invalid property value: %d\n",
585 strarr_free(mod
, entity_refs
, nelems
);
586 topo_mod_ipmi_rele(mod
);
587 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
589 ledmode
= (uint8_t)mode_in
;
590 if (ipmi_sunoem_led_set(hdl
, gdl
, ledmode
) < 0) {
591 topo_mod_dprintf(mod
, "%s: Failed to set LED mode for "
592 "%s (%s) to %s\n", __func__
, entity_refs
[i
],
593 ipmi_errmsg(hdl
), ledmode
? "ON" : "OFF");
594 strarr_free(mod
, entity_refs
, nelems
);
595 topo_mod_ipmi_rele(mod
);
602 if (ipmi_sunoem_led_get(hdl
, gdl
, &ledmode
) < 0) {
603 topo_mod_dprintf(mod
, "%s: Failed to get LED mode for "
604 "%s (%s)\n", __func__
, entity_refs
[i
],
606 strarr_free(mod
, entity_refs
, nelems
);
607 topo_mod_ipmi_rele(mod
);
611 strarr_free(mod
, entity_refs
, nelems
);
612 topo_mod_ipmi_rele(mod
);
614 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
615 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, TOPO_LED_MODE
) != 0 ||
616 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
617 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, ledmode
) != 0) {
618 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
620 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
628 * On most Sun platforms there is no seperate locate LED for the drive bays.
629 * This propmethod simulates a locate LED by blinking the ok2rm LED.
631 * LED control is through a the Sun OEM led/get commands. This propmethod can
632 * work on X4500/X4540 with ILOM 2.x and on
633 * X4140/X4240/X4440/X4500/X4540/X4150/X4250 and X4450 platforms with ILOM 3.x.
636 bay_locate_mode(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
637 nvlist_t
*in
, nvlist_t
**out
)
641 ipmi_sdr_generic_locator_t
*gdl
= NULL
;
646 nvlist_t
*pargs
, *nvl
;
647 boolean_t found_sdr
= B_FALSE
;
649 if (vers
> TOPO_METH_BAY_LOCATE_VERSION
)
650 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
653 * Get an IPMI handle and then lookup the generic device locator sensor
654 * data record referenced by the entity_ref prop val
656 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
657 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
661 if (topo_prop_get_string_array(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
662 &entity_refs
, &nelems
, &err
) != 0) {
663 topo_mod_dprintf(mod
, "Failed to lookup entity_ref property "
664 "(%s)", topo_strerror(err
));
665 topo_mod_ipmi_rele(mod
);
666 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
669 for (i
= 0; i
< nelems
; i
++) {
670 if ((gdl
= ipmi_sdr_lookup_generic(hdl
, entity_refs
[i
]))
675 topo_mod_dprintf(mod
, "Failed to lookup SDR for %s "
676 "(%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
680 strarr_free(mod
, entity_refs
, nelems
);
681 topo_mod_ipmi_rele(mod
);
686 * Now look for a private argument list to figure out whether we're
687 * doing a get or a set operation, and then do it.
689 if ((nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &pargs
) == 0) &&
690 nvlist_exists(pargs
, TOPO_PROP_VAL_VAL
)) {
694 if ((ret
= nvlist_lookup_uint32(pargs
, TOPO_PROP_VAL_VAL
,
696 topo_mod_dprintf(mod
, "Failed to lookup %s nvpair "
697 "(%s)\n", TOPO_PROP_VAL_VAL
, strerror(ret
));
698 strarr_free(mod
, entity_refs
, nelems
);
699 topo_mod_ipmi_rele(mod
);
700 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
702 if (mode_in
!= TOPO_LED_STATE_OFF
&&
703 mode_in
!= TOPO_LED_STATE_ON
) {
704 topo_mod_dprintf(mod
, "Invalid property value: %d\n",
706 strarr_free(mod
, entity_refs
, nelems
);
707 topo_mod_ipmi_rele(mod
);
708 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
710 if (mode_in
== TOPO_LED_STATE_ON
)
711 ledmode
= IPMI_SUNOEM_LED_MODE_FAST
;
713 ledmode
= IPMI_SUNOEM_LED_MODE_OFF
;
714 if (ipmi_sunoem_led_set(hdl
, gdl
, ledmode
) < 0) {
715 topo_mod_dprintf(mod
, "Failed to set LED mode for %s "
716 "(%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
717 strarr_free(mod
, entity_refs
, nelems
);
718 topo_mod_ipmi_rele(mod
);
725 if (ipmi_sunoem_led_get(hdl
, gdl
, &ledmode
) < 0) {
726 topo_mod_dprintf(mod
, "Failed to get LED mode for %s "
727 "(%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
728 strarr_free(mod
, entity_refs
, nelems
);
729 topo_mod_ipmi_rele(mod
);
733 strarr_free(mod
, entity_refs
, nelems
);
734 topo_mod_ipmi_rele(mod
);
736 if (ledmode
== IPMI_SUNOEM_LED_MODE_SLOW
||
737 ledmode
== IPMI_SUNOEM_LED_MODE_FAST
)
738 ledmode
= TOPO_LED_STATE_ON
;
740 ledmode
= TOPO_LED_STATE_OFF
;
742 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
743 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, TOPO_LED_MODE
) != 0 ||
744 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
745 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, ledmode
) != 0) {
746 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
748 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
756 * This is a method for the "mode" property that is specific for the ok2rm and
757 * service drive bay LED's on the X4500/X4540 platforms running ILOM 2.x and
758 * for X4140/X4240/X4440/X4500/X4540/X4150/X4250 and X4450 platforms running
761 * For ILOM 2.x, the LED's are controlled by a Sun OEM led set command
763 * For ILOM 3.x platforms the LED's are controlled by sending a platform event
764 * message for the appropriate DBP/HDD##/STATE compact SDR.
766 * For both ILOM 2 and ILOM 3, the current LED mode can be obtained by a
767 * Sun OEM led get command.
770 bay_indicator_mode(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
771 nvlist_t
*in
, nvlist_t
**out
)
775 ipmi_sdr_compact_sensor_t
*cs
= NULL
;
776 ipmi_sdr_generic_locator_t
*gdl
= NULL
;
777 ipmi_deviceid_t
*sp_devid
;
778 ipmi_platform_event_message_t pem
;
781 uint32_t type
, ledmode
;
782 uint8_t mode_in
, ev_off
;
783 nvlist_t
*pargs
, *nvl
;
784 boolean_t found_sdr
= B_FALSE
;
786 if (vers
> TOPO_METH_BAY_MODE_VERSION
)
787 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
789 if (topo_prop_get_uint32(node
, TOPO_PGROUP_FACILITY
, TOPO_FACILITY_TYPE
,
791 topo_mod_dprintf(mod
, "Failed to lookup %s property "
792 "(%s)", TOPO_FACILITY_TYPE
, topo_strerror(err
));
793 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
796 case (TOPO_LED_TYPE_SERVICE
):
799 case (TOPO_LED_TYPE_OK2RM
):
803 topo_mod_dprintf(mod
, "Invalid LED type: 0x%x\n", type
);
804 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
807 if (topo_prop_get_string_array(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
808 &entity_refs
, &nelems
, &err
) != 0) {
809 topo_mod_dprintf(mod
, "Failed to lookup entity_ref property "
810 "(%s)", topo_strerror(err
));
811 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
815 * Figure out whether the SP is running ILOM 2.x or ILOM 3.x
817 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
818 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
819 strarr_free(mod
, entity_refs
, nelems
);
823 if ((sp_devid
= ipmi_get_deviceid(hdl
)) == NULL
) {
824 topo_mod_dprintf(mod
, "%s: GET DEVICEID command failed (%s)\n",
825 __func__
, ipmi_errmsg(hdl
));
826 strarr_free(mod
, entity_refs
, nelems
);
827 topo_mod_ipmi_rele(mod
);
832 * Now lookup the propmethod argument list and figure out whether we're
833 * doing a get or a set operation, and then do it.
835 if ((nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &pargs
) == 0) &&
836 nvlist_exists(pargs
, TOPO_PROP_VAL_VAL
)) {
840 if ((ret
= nvlist_lookup_uint32(pargs
, TOPO_PROP_VAL_VAL
,
842 topo_mod_dprintf(mod
, "Failed to lookup %s nvpair "
843 "(%s)\n", TOPO_PROP_VAL_VAL
, strerror(ret
));
844 strarr_free(mod
, entity_refs
, nelems
);
845 topo_mod_ipmi_rele(mod
);
846 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
849 topo_mod_dprintf(mod
, "%s: Setting LED mode to %s\n", __func__
,
850 ledmode
? "ON" : "OFF");
852 if (sp_devid
->id_firm_major
== 2) {
853 for (i
= 0; i
< nelems
; i
++) {
854 if ((gdl
= ipmi_sdr_lookup_generic(hdl
,
855 entity_refs
[i
])) != NULL
) {
859 topo_mod_dprintf(mod
,
860 "Failed to lookup SDR for %s(%s)\n",
861 entity_refs
[i
], ipmi_errmsg(hdl
));
865 strarr_free(mod
, entity_refs
, nelems
);
866 topo_mod_ipmi_rele(mod
);
870 if (ipmi_sunoem_led_set(hdl
, gdl
, (uint8_t)ledmode
)
872 topo_mod_dprintf(mod
,
873 "Failed to set LED mode for %s (%s)\n",
874 entity_refs
[i
], ipmi_errmsg(hdl
));
875 strarr_free(mod
, entity_refs
, nelems
);
876 topo_mod_ipmi_rele(mod
);
880 for (i
= 0; i
< nelems
; i
++) {
881 if ((cs
= ipmi_sdr_lookup_compact_sensor(hdl
,
882 entity_refs
[i
])) != NULL
) {
886 topo_mod_dprintf(mod
,
887 "Failed to lookup SDR for %s(%s)\n",
888 entity_refs
[i
], ipmi_errmsg(hdl
));
892 strarr_free(mod
, entity_refs
, nelems
);
893 topo_mod_ipmi_rele(mod
);
897 pem
.ipem_generator
= IPMI_SEL_SYSTEM
;
898 pem
.ipem_rev
= IPMI_EV_REV15
;
899 pem
.ipem_sensor_type
= IPMI_ST_BAY
;
900 pem
.ipem_sensor_num
= cs
->is_cs_number
;
901 pem
.ipem_event_type
= IPMI_RT_SPECIFIC
;
902 if (ledmode
== TOPO_LED_STATE_ON
)
903 pem
.ipem_event_dir
= 0;
905 pem
.ipem_event_dir
= 1;
907 pem
.ipem_event_data
[0] = ev_off
;
908 pem
.ipem_event_data
[1] = 0xff;
909 pem
.ipem_event_data
[2] = 0xff;
911 if (ipmi_event_platform_message(hdl
, &pem
) != 0) {
912 topo_mod_dprintf(mod
, "%s: Failed to send "
913 "platform event mesg for %s (%s)\n",
914 __func__
, entity_refs
[i
], ipmi_errmsg(hdl
));
915 strarr_free(mod
, entity_refs
, nelems
);
916 topo_mod_ipmi_rele(mod
);
924 for (i
= 0; i
< nelems
; i
++) {
925 if ((gdl
= ipmi_sdr_lookup_generic(hdl
, entity_refs
[i
]))
930 topo_mod_dprintf(mod
, "%s: Failed to lookup "
931 "SDR for %s (%s)\n", __func__
,
932 entity_refs
[i
], ipmi_errmsg(hdl
));
936 strarr_free(mod
, entity_refs
, nelems
);
937 topo_mod_ipmi_rele(mod
);
940 if (ipmi_sunoem_led_get(hdl
, gdl
, &mode_in
) < 0) {
941 topo_mod_dprintf(mod
, "%s: Failed to get LED mode for "
942 "%s (%s)\n", __func__
, entity_refs
[i
],
944 strarr_free(mod
, entity_refs
, nelems
);
945 topo_mod_ipmi_rele(mod
);
950 strarr_free(mod
, entity_refs
, nelems
);
951 topo_mod_ipmi_rele(mod
);
953 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
954 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, TOPO_LED_MODE
) != 0 ||
955 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
956 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, ledmode
) != 0) {
957 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
959 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
966 * This propmethod is for controlling the present LED on the drive bays for
967 * the X4500 platform.
970 x4500_present_mode(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
971 nvlist_t
*in
, nvlist_t
**out
)
975 ipmi_sdr_compact_sensor_t
*cs
= NULL
;
976 ipmi_set_sensor_reading_t sr_out
= { 0 };
980 nvlist_t
*pargs
, *nvl
;
981 boolean_t found_sdr
= B_FALSE
;
983 if (vers
> TOPO_METH_X4500_MODE_VERSION
)
984 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
986 if (topo_prop_get_string_array(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
987 &entity_refs
, &nelems
, &err
) != 0) {
988 topo_mod_dprintf(mod
, "Failed to lookup entity_ref property "
989 "(%s)", topo_strerror(err
));
990 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
993 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
994 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
995 strarr_free(mod
, entity_refs
, nelems
);
998 for (i
= 0; i
< nelems
; i
++) {
999 if ((cs
= ipmi_sdr_lookup_compact_sensor(hdl
, entity_refs
[i
]))
1004 topo_mod_dprintf(mod
, "Failed to lookup SDR for %s "
1005 "(%s)\n", entity_refs
[i
],
1010 strarr_free(mod
, entity_refs
, nelems
);
1011 topo_mod_ipmi_rele(mod
);
1016 * Now lookup the propmethod argument list and figure out whether we're
1017 * doing a get or a set operation, and then do it.
1019 if ((nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &pargs
) == 0) &&
1020 nvlist_exists(pargs
, TOPO_PROP_VAL_VAL
)) {
1024 if ((ret
= nvlist_lookup_uint32(pargs
, TOPO_PROP_VAL_VAL
,
1026 topo_mod_dprintf(mod
, "Failed to lookup %s nvpair "
1027 "(%s)\n", TOPO_PROP_VAL_VAL
, strerror(ret
));
1028 strarr_free(mod
, entity_refs
, nelems
);
1029 topo_mod_ipmi_rele(mod
);
1030 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1033 topo_mod_dprintf(mod
, "%s: Setting LED mode to %s\n", __func__
,
1034 ledmode
? "ON" : "OFF");
1036 if (ledmode
== TOPO_LED_STATE_OFF
) {
1037 sr_out
.iss_deassert_state
= BAY_PRESENT_LED_MASK
;
1038 sr_out
.iss_deassrt_op
= IPMI_SENSOR_OP_SET
;
1039 } else if (ledmode
== TOPO_LED_STATE_ON
) {
1040 sr_out
.iss_assert_state
= BAY_PRESENT_LED_MASK
;
1041 sr_out
.iss_assert_op
= IPMI_SENSOR_OP_SET
;
1043 topo_mod_dprintf(mod
, "%s: Invalid LED mode: "
1044 "%d\n", __func__
, ledmode
);
1045 strarr_free(mod
, entity_refs
, nelems
);
1046 topo_mod_ipmi_rele(mod
);
1049 sr_out
.iss_id
= cs
->is_cs_number
;
1050 topo_mod_dprintf(mod
, "Setting LED mode (mask=0x%x)\n",
1051 BAY_PRESENT_LED_MASK
);
1052 if (ipmi_set_sensor_reading(hdl
, &sr_out
) != 0) {
1053 topo_mod_dprintf(mod
, "%s: Failed to set "
1054 "sensor reading for %s (%s)\n", __func__
,
1055 entity_refs
[i
], ipmi_errmsg(hdl
));
1056 strarr_free(mod
, entity_refs
, nelems
);
1057 topo_mod_ipmi_rele(mod
);
1064 ipmi_sensor_reading_t
*sr_in
;
1066 topo_mod_dprintf(mod
, "Getting LED mode\n");
1067 if ((sr_in
= ipmi_get_sensor_reading(hdl
, cs
->is_cs_number
))
1069 topo_mod_dprintf(mod
, "Failed to get sensor reading "
1070 "for sensor %s (sensor num: %d) (error: %s)\n",
1071 entity_refs
[i
], cs
->is_cs_number
, ipmi_errmsg(hdl
));
1072 strarr_free(mod
, entity_refs
, nelems
);
1073 topo_mod_ipmi_rele(mod
);
1076 if (sr_in
->isr_state
& (uint16_t)BAY_PRESENT_LED_MASK
)
1077 ledmode
= TOPO_LED_STATE_ON
;
1079 ledmode
= TOPO_LED_STATE_OFF
;
1081 strarr_free(mod
, entity_refs
, nelems
);
1082 topo_mod_ipmi_rele(mod
);
1084 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
1085 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, TOPO_LED_MODE
) != 0 ||
1086 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
1087 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, ledmode
) != 0) {
1088 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
1090 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1097 * This is a property method for controlling the chassis service LED on
1098 * ILOM 3.x based platforms.
1101 chassis_service_mode(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
1102 nvlist_t
*in
, nvlist_t
**out
)
1106 ipmi_sdr_generic_locator_t
*gdl
= NULL
;
1107 ipmi_deviceid_t
*sp_devid
;
1108 ipmi_platform_event_message_t pem
;
1113 nvlist_t
*pargs
, *nvl
;
1114 boolean_t found_sdr
= B_FALSE
;
1116 if (vers
> TOPO_METH_CHASSIS_SERVICE_VERSION
)
1117 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1120 * Get an IPMI handle and then lookup the generic device locator record
1121 * referenced by the entity_ref prop val
1123 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
1124 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
1128 if (topo_prop_get_string_array(node
, TOPO_PGROUP_FACILITY
, "entity_ref",
1129 &entity_refs
, &nelems
, &err
) != 0) {
1130 topo_mod_dprintf(mod
, "Failed to lookup entity_ref property "
1131 "(%s)", topo_strerror(err
));
1132 topo_mod_ipmi_rele(mod
);
1133 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1136 for (i
= 0; i
< nelems
; i
++) {
1137 if ((gdl
= ipmi_sdr_lookup_generic(hdl
, entity_refs
[i
]))
1142 topo_mod_dprintf(mod
, "Failed to lookup SDR for %s "
1143 "(%s)\n", entity_refs
[i
], ipmi_errmsg(hdl
));
1147 strarr_free(mod
, entity_refs
, nelems
);
1148 topo_mod_ipmi_rele(mod
);
1153 * Now lookup the propmethod argument list and figure out whether we're
1154 * doing a get or a set operation, and then do it.
1156 if ((nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &pargs
) == 0) &&
1157 nvlist_exists(pargs
, TOPO_PROP_VAL_VAL
)) {
1161 if ((ret
= nvlist_lookup_uint32(pargs
, TOPO_PROP_VAL_VAL
,
1163 topo_mod_dprintf(mod
, "Failed to lookup %s nvpair "
1164 "(%s)\n", TOPO_PROP_VAL_VAL
, strerror(ret
));
1165 strarr_free(mod
, entity_refs
, nelems
);
1166 topo_mod_ipmi_rele(mod
);
1167 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1171 * Determine which IPMI mechanism to use to set the LED mode
1172 * based on whether the SP is running ILOM 2 or later.
1174 if ((sp_devid
= ipmi_get_deviceid(hdl
)) == NULL
) {
1175 topo_mod_dprintf(mod
, "%s: GET DEVICEID command failed "
1176 "(%s)\n", __func__
, ipmi_errmsg(hdl
));
1177 strarr_free(mod
, entity_refs
, nelems
);
1178 topo_mod_ipmi_rele(mod
);
1182 topo_mod_dprintf(mod
, "%s: Setting LED mode to %s\n", __func__
,
1183 mode_in
? "ON" : "OFF");
1185 if (sp_devid
->id_firm_major
== 2) {
1186 if (mode_in
!= TOPO_LED_STATE_OFF
&&
1187 mode_in
!= TOPO_LED_STATE_ON
) {
1188 topo_mod_dprintf(mod
, "Invalid property value: "
1190 strarr_free(mod
, entity_refs
, nelems
);
1191 topo_mod_ipmi_rele(mod
);
1192 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1194 if (ipmi_sunoem_led_set(hdl
, gdl
, (uint8_t)mode_in
)
1196 topo_mod_dprintf(mod
, "Failed to set LED mode "
1197 "for %s (%s)\n", entity_refs
[i
],
1199 strarr_free(mod
, entity_refs
, nelems
);
1200 topo_mod_ipmi_rele(mod
);
1204 pem
.ipem_generator
= IPMI_SEL_SYSTEM
;
1205 pem
.ipem_rev
= IPMI_EV_REV15
;
1206 pem
.ipem_sensor_type
= IPMI_ST_SYSTEM
;
1207 pem
.ipem_sensor_num
= 0x00;
1208 pem
.ipem_event_type
= IPMI_RT_SPECIFIC
;
1209 if (mode_in
== TOPO_LED_STATE_ON
)
1210 pem
.ipem_event_dir
= 0;
1212 pem
.ipem_event_dir
= 1;
1214 pem
.ipem_event_data
[0] = 0x02;
1215 pem
.ipem_event_data
[1] = 0xff;
1216 pem
.ipem_event_data
[2] = 0xff;
1218 topo_mod_dprintf(mod
, "Sending platform event\n");
1219 if (ipmi_event_platform_message(hdl
, &pem
) != 0) {
1220 topo_mod_dprintf(mod
, "%s: Failed to send "
1221 "platform event mesg for sensor 0 (%s)\n",
1222 __func__
, ipmi_errmsg(hdl
));
1223 strarr_free(mod
, entity_refs
, nelems
);
1224 topo_mod_ipmi_rele(mod
);
1232 if (ipmi_sunoem_led_get(hdl
, gdl
, &ledmode
) < 0) {
1233 topo_mod_dprintf(mod
, "%s: Failed to get LED mode for "
1234 "%s (%s)\n", __func__
, entity_refs
[i
],
1236 strarr_free(mod
, entity_refs
, nelems
);
1237 topo_mod_ipmi_rele(mod
);
1241 strarr_free(mod
, entity_refs
, nelems
);
1242 topo_mod_ipmi_rele(mod
);
1244 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
1245 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, TOPO_LED_MODE
) != 0 ||
1246 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
1247 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, ledmode
) != 0) {
1248 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
1250 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1257 * This is a property method for controlling the chassis identify LED using
1258 * generic IPMI mechanisms.
1262 chassis_ident_mode(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
1263 nvlist_t
*in
, nvlist_t
**out
)
1268 boolean_t assert_ident
;
1269 nvlist_t
*pargs
, *nvl
;
1270 ipmi_chassis_status_t
*chs
;
1272 if (vers
> TOPO_METH_CHASSIS_IDENT_VERSION
)
1273 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1275 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
1276 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
1281 * Now lookup the propmethod argument list and figure out whether we're
1282 * doing a get or a set operation, and then do it.
1284 if ((nvlist_lookup_nvlist(in
, TOPO_PROP_PARGS
, &pargs
) == 0) &&
1285 nvlist_exists(pargs
, TOPO_PROP_VAL_VAL
)) {
1289 if ((ret
= nvlist_lookup_uint32(pargs
, TOPO_PROP_VAL_VAL
,
1291 topo_mod_dprintf(mod
, "Failed to lookup %s nvpair "
1292 "(%s)\n", TOPO_PROP_VAL_VAL
, strerror(ret
));
1293 topo_mod_ipmi_rele(mod
);
1294 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1297 assert_ident
= modeval
? B_TRUE
: B_FALSE
;
1298 topo_mod_dprintf(mod
, "%s: Setting LED mode to %s\n", __func__
,
1299 assert_ident
? "ON" : "OFF");
1300 if (ipmi_chassis_identify(hdl
, assert_ident
) != 0) {
1301 topo_mod_ipmi_rele(mod
);
1302 return (topo_mod_seterrno(mod
, EMOD_UNKNOWN
));
1309 if ((chs
= ipmi_chassis_status(hdl
)) == NULL
||
1310 !chs
->ichs_identify_supported
) {
1312 topo_mod_ipmi_rele(mod
);
1313 return (topo_mod_seterrno(mod
, EMOD_UNKNOWN
));
1316 * ichs_identify_state is a 2-bit value with the following
1319 * 1 - ident is temporarily on
1320 * 2 - ident is indefinitely on
1323 switch (chs
->ichs_identify_state
) {
1325 modeval
= TOPO_LED_STATE_OFF
;
1329 modeval
= TOPO_LED_STATE_ON
;
1333 topo_mod_ipmi_rele(mod
);
1334 return (topo_mod_seterrno(mod
, EMOD_UNKNOWN
));
1338 topo_mod_ipmi_rele(mod
);
1340 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
1341 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, TOPO_LED_MODE
) != 0 ||
1342 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
, TOPO_TYPE_UINT32
) != 0 ||
1343 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_VAL
, modeval
) != 0) {
1344 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
1346 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1353 make_sensor_node(topo_mod_t
*mod
, tnode_t
*pnode
, struct sensor_data
*sd
)
1357 char *ftype
= "sensor", facname
[MAX_ID_LEN
], **entity_refs
;
1358 topo_pgroup_info_t pgi
;
1359 nvlist_t
*arg_nvl
= NULL
;
1362 * Some platforms have '/' characters in the IPMI entity name, but '/'
1363 * has a special meaning for FMRI's so we change them to '.' before
1364 * binding the node into the topology.
1366 (void) strcpy(facname
, sd
->sd_entity_ref
);
1367 for (i
= 0; facname
[i
]; i
++)
1368 if (facname
[i
] == '/')
1371 if ((fnode
= topo_node_facbind(mod
, pnode
, facname
, ftype
)) == NULL
) {
1372 topo_mod_dprintf(mod
, "Failed to bind facility node: %s\n",
1374 /* topo errno set */
1378 pgi
.tpi_name
= TOPO_PGROUP_FACILITY
;
1379 pgi
.tpi_namestab
= TOPO_STABILITY_PRIVATE
;
1380 pgi
.tpi_datastab
= TOPO_STABILITY_PRIVATE
;
1381 pgi
.tpi_version
= 1;
1382 if (topo_pgroup_create(fnode
, &pgi
, &err
) != 0) {
1383 if (err
!= ETOPO_PROP_DEFD
) {
1384 topo_mod_dprintf(mod
, "pgroups create failure: %s\n",
1385 topo_strerror(err
));
1386 topo_node_unbind(fnode
);
1390 if (topo_method_register(mod
, fnode
, ipmi_fac_methods
) < 0) {
1391 topo_mod_dprintf(mod
, "make_fac_node: "
1392 "failed to register facility methods");
1393 topo_node_unbind(fnode
);
1397 * For both threshold and discrete sensors we set up a propmethod for
1398 * getting the sensor state and properties to hold the entity ref,
1399 * sensor class and sensor type.
1401 * Additionally, for analog sensors we set up a property method for
1402 * getting the converted sensor reading and property for the base
1405 if ((entity_refs
= topo_mod_alloc(mod
, sizeof (char *))) == NULL
)
1406 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1408 entity_refs
[0] = topo_mod_strdup(mod
, sd
->sd_entity_ref
);
1410 if (topo_prop_set_string_array(fnode
, TOPO_PGROUP_FACILITY
,
1411 "entity_ref", TOPO_PROP_IMMUTABLE
, (const char **)entity_refs
, 1,
1413 topo_mod_dprintf(mod
, "%s: Failed to set entity_ref property "
1414 "on node: %s=%d (%s)\n", __func__
, topo_node_name(fnode
),
1415 topo_node_instance(fnode
), topo_strerror(err
));
1416 strarr_free(mod
, entity_refs
, 1);
1419 strarr_free(mod
, entity_refs
, 1);
1421 if (topo_prop_set_string(fnode
, TOPO_PGROUP_FACILITY
, TOPO_SENSOR_CLASS
,
1422 TOPO_PROP_IMMUTABLE
, sd
->sd_class
, &err
) != 0) {
1423 topo_mod_dprintf(mod
, "Failed to set %s property on node: "
1424 "%s=%d (%s)\n", TOPO_SENSOR_CLASS
, topo_node_name(fnode
),
1425 topo_node_instance(fnode
), topo_strerror(err
));
1428 if (topo_prop_set_uint32(fnode
, TOPO_PGROUP_FACILITY
,
1429 TOPO_FACILITY_TYPE
, TOPO_PROP_IMMUTABLE
, sd
->sd_stype
, &err
) != 0) {
1430 topo_mod_dprintf(mod
, "Failed to set %s property on node: "
1431 "%s=%d (%s)\n", TOPO_FACILITY_TYPE
, topo_node_name(fnode
),
1432 topo_node_instance(fnode
), topo_strerror(err
));
1435 if (topo_mod_nvalloc(mod
, &arg_nvl
, NV_UNIQUE_NAME
) < 0) {
1436 topo_node_unbind(fnode
);
1437 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1440 if ((ret
= nvlist_add_string(arg_nvl
, "ipmi_entity", sd
->sd_entity_ref
))
1442 topo_mod_dprintf(mod
, "Failed build arg nvlist (%s)\n",
1444 nvlist_free(arg_nvl
);
1448 if (topo_prop_method_register(fnode
, TOPO_PGROUP_FACILITY
,
1449 TOPO_SENSOR_STATE
, TOPO_TYPE_UINT32
, "ipmi_sensor_state", arg_nvl
,
1451 topo_mod_dprintf(mod
, "Failed to register %s propmeth on fac "
1452 "node %s (%s)\n", TOPO_SENSOR_STATE
, topo_node_name(fnode
),
1453 topo_strerror(err
));
1454 nvlist_free(arg_nvl
);
1458 if (strcmp(sd
->sd_class
, TOPO_SENSOR_CLASS_THRESHOLD
) == 0) {
1459 if (topo_prop_method_register(fnode
, TOPO_PGROUP_FACILITY
,
1460 TOPO_SENSOR_READING
, TOPO_TYPE_DOUBLE
,
1461 "ipmi_sensor_reading", arg_nvl
, &err
) != 0) {
1462 topo_mod_dprintf(mod
, "Failed to register %s propmeth "
1463 "on fac node %s (%s)\n", TOPO_SENSOR_READING
,
1464 topo_node_name(fnode
), topo_strerror(err
));
1465 nvlist_free(arg_nvl
);
1468 if (topo_prop_set_uint32(fnode
, TOPO_PGROUP_FACILITY
,
1469 TOPO_SENSOR_UNITS
, TOPO_PROP_IMMUTABLE
, sd
->sd_units
, &err
)
1471 topo_mod_dprintf(mod
, "Failed to set units property on "
1472 "node: %s (%s)\n", topo_node_name(fnode
),
1473 topo_strerror(err
));
1474 nvlist_free(arg_nvl
);
1478 nvlist_free(arg_nvl
);
1483 seq_search(char *key
, char **list
, uint_t nelem
)
1485 for (int i
= 0; i
< nelem
; i
++)
1486 if (strcmp(key
, list
[i
]) == 0)
1493 sdr_callback(ipmi_handle_t
*hdl
, const char *id
, ipmi_sdr_t
*sdr
, void *data
)
1495 uint8_t sensor_entity
, sensor_inst
;
1497 ipmi_sdr_full_sensor_t
*f_sensor
= NULL
;
1498 ipmi_sdr_compact_sensor_t
*c_sensor
= NULL
;
1499 struct sensor_data sd
;
1500 struct entity_info
*ei
= (struct entity_info
*)data
;
1502 switch (sdr
->is_type
) {
1503 case IPMI_SDR_TYPE_FULL_SENSOR
:
1505 (ipmi_sdr_full_sensor_t
*)sdr
->is_record
;
1506 sensor_entity
= f_sensor
->is_fs_entity_id
;
1507 sensor_inst
= f_sensor
->is_fs_entity_instance
;
1508 sensor_idlen
= f_sensor
->is_fs_idlen
;
1509 (void) strncpy(sd
.sd_entity_ref
,
1510 f_sensor
->is_fs_idstring
,
1511 f_sensor
->is_fs_idlen
);
1512 sd
.sd_entity_ref
[sensor_idlen
] = '\0';
1513 sd
.sd_units
= f_sensor
->is_fs_unit2
;
1514 sd
.sd_stype
= f_sensor
->is_fs_type
;
1515 sd
.sd_rtype
= f_sensor
->is_fs_reading_type
;
1517 case IPMI_SDR_TYPE_COMPACT_SENSOR
:
1519 (ipmi_sdr_compact_sensor_t
*)sdr
->is_record
;
1520 sensor_entity
= c_sensor
->is_cs_entity_id
;
1521 sensor_inst
= c_sensor
->is_cs_entity_instance
;
1522 sensor_idlen
= c_sensor
->is_cs_idlen
;
1523 (void) strncpy(sd
.sd_entity_ref
,
1524 c_sensor
->is_cs_idstring
,
1526 sd
.sd_entity_ref
[sensor_idlen
] = '\0';
1527 sd
.sd_units
= c_sensor
->is_cs_unit2
;
1528 sd
.sd_stype
= c_sensor
->is_cs_type
;
1529 sd
.sd_rtype
= c_sensor
->is_cs_reading_type
;
1534 if (sd
.sd_rtype
== IPMI_RT_THRESHOLD
)
1535 sd
.sd_class
= TOPO_SENSOR_CLASS_THRESHOLD
;
1537 sd
.sd_class
= TOPO_SENSOR_CLASS_DISCRETE
;
1540 * We offset the threshold and generic sensor reading types by 0x100
1542 if (sd
.sd_rtype
>= 0x1 && sd
.sd_rtype
<= 0xc)
1543 sd
.sd_stype
= sd
.sd_rtype
+ 0x100;
1545 if ((ei
->ei_list
!= NULL
&& seq_search(sd
.sd_entity_ref
,
1546 ei
->ei_list
, ei
->ei_listsz
) == B_TRUE
) ||
1547 (sensor_entity
== ei
->ei_id
&& sensor_inst
== ei
->ei_inst
)) {
1549 if (make_sensor_node(ei
->ei_mod
, ei
->ei_node
, &sd
) != 0) {
1550 topo_mod_dprintf(ei
->ei_mod
, "Failed to create sensor "
1551 "node for %s\n", sd
.sd_entity_ref
);
1552 if (topo_mod_errno(ei
->ei_mod
) != EMOD_NODE_DUP
)
1560 get_entity_info(topo_mod_t
*mod
, tnode_t
*node
, ipmi_handle_t
*hdl
,
1561 struct entity_info
*ei
)
1566 ipmi_sdr_t
*ref_sdr
;
1567 ipmi_sdr_full_sensor_t
*fsensor
;
1568 ipmi_sdr_compact_sensor_t
*csensor
;
1569 ipmi_sdr_fru_locator_t
*floc
;
1570 ipmi_sdr_generic_locator_t
*gloc
;
1571 boolean_t found_sdr
= B_FALSE
;
1574 * Use the entity ref to lookup the SDR, which will have the entity ID
1577 if (topo_prop_get_string_array(node
, TOPO_PGROUP_IPMI
,
1578 "entity_ref", &entity_refs
, &nelems
, &err
) != 0) {
1579 topo_mod_dprintf(mod
, "%s: Failed to lookup entity_ref "
1580 "property on %s=%d (%s)\n", __func__
, topo_node_name(node
),
1581 topo_node_instance(node
), topo_strerror(err
));
1582 topo_mod_ipmi_rele(mod
);
1583 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1586 for (int i
= 0; i
< nelems
; i
++) {
1587 if ((ref_sdr
= ipmi_sdr_lookup(hdl
, entity_refs
[i
])) != NULL
) {
1591 topo_mod_dprintf(mod
, "%s: Failed to lookup SDR for %s "
1592 "(%s)\n", __func__
, entity_refs
[i
],
1595 strarr_free(mod
, entity_refs
, nelems
);
1597 topo_mod_ipmi_rele(mod
);
1601 switch (ref_sdr
->is_type
) {
1602 case IPMI_SDR_TYPE_FULL_SENSOR
:
1603 fsensor
= (ipmi_sdr_full_sensor_t
*)ref_sdr
->is_record
;
1604 ei
->ei_id
= fsensor
->is_fs_entity_id
;
1605 ei
->ei_inst
= fsensor
->is_fs_entity_instance
;
1607 case IPMI_SDR_TYPE_COMPACT_SENSOR
:
1609 = (ipmi_sdr_compact_sensor_t
*)ref_sdr
->is_record
;
1610 ei
->ei_id
= csensor
->is_cs_entity_id
;
1611 ei
->ei_inst
= csensor
->is_cs_entity_instance
;
1613 case IPMI_SDR_TYPE_FRU_LOCATOR
:
1614 floc
= (ipmi_sdr_fru_locator_t
*)ref_sdr
->is_record
;
1615 ei
->ei_id
= floc
->is_fl_entity
;
1616 ei
->ei_inst
= floc
->is_fl_instance
;
1618 case IPMI_SDR_TYPE_GENERIC_LOCATOR
:
1619 gloc
= (ipmi_sdr_generic_locator_t
*)ref_sdr
->is_record
;
1620 ei
->ei_id
= gloc
->is_gl_entity
;
1621 ei
->ei_inst
= gloc
->is_gl_instance
;
1624 topo_mod_dprintf(mod
, "Failed to determine entity id "
1625 "and instance\n", ipmi_errmsg(hdl
));
1626 topo_mod_ipmi_rele(mod
);
1627 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1634 ipmi_sensor_enum(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
1635 nvlist_t
*in
, nvlist_t
**out
)
1638 struct entity_info ei
= {0};
1641 if ((hdl
= topo_mod_ipmi_hold(mod
)) == NULL
) {
1642 topo_mod_dprintf(mod
, "Failed to get IPMI handle\n");
1647 * For cases where the records in the SDR are hopelessly broken, then
1648 * we'll resort to hardcoding a list of sensor entities that should be
1649 * bound to this particular node. Otherwise, we'll first check if the
1650 * properties for the associated IPMI entity id and instance exist. If
1651 * not, we check for a property referencing an IPMI entity name on which
1652 * we can lookup the entity ID and instance. If none of the above pans
1653 * out, then we bail out.
1655 if (topo_prop_get_string_array(node
, TOPO_PGROUP_IPMI
,
1656 TOPO_PROP_IPMI_ENTITY_LIST
, &ei
.ei_list
, &ei
.ei_listsz
, &err
)
1657 != 0 && (topo_prop_get_uint32(node
, TOPO_PGROUP_IPMI
,
1658 TOPO_PROP_IPMI_ENTITY_ID
, &ei
.ei_id
, &err
) != 0 ||
1659 topo_prop_get_uint32(node
, TOPO_PGROUP_IPMI
,
1660 TOPO_PROP_IPMI_ENTITY_INST
, &ei
.ei_inst
, &err
) != 0)) {
1661 if (get_entity_info(mod
, node
, hdl
, &ei
) != 0)
1668 * Now iterate through all of the full and compact sensor data records
1669 * and create a sensor facility node for each record that matches our
1670 * entity ID and instance
1672 if ((ret
= ipmi_sdr_iter(hdl
, sdr_callback
, &ei
)) != 0) {
1673 topo_mod_dprintf(mod
, "ipmi_sdr_iter() failed\n");
1676 topo_mod_ipmi_rele(mod
);
1677 if (ei
.ei_list
!= NULL
)
1678 strarr_free(mod
, ei
.ei_list
, ei
.ei_listsz
);
1684 ipmi_entity(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
1685 nvlist_t
*in
, nvlist_t
**out
)
1687 char **fmtarr
, **entity_refs
, buf
[BUFSZ
];
1690 int ret
, inst1
, inst2
;
1691 uint32_t offset
, nparams
;
1692 nvlist_t
*args
, *nvl
;
1694 if (vers
> TOPO_METH_IPMI_ENTITY_VERSION
)
1695 return (topo_mod_seterrno(mod
, ETOPO_METHOD_VERNEW
));
1697 if ((ret
= nvlist_lookup_nvlist(in
, TOPO_PROP_ARGS
, &args
)) != 0) {
1698 topo_mod_dprintf(mod
, "Failed to lookup 'args' list (%s)\n",
1700 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1702 if ((ret
= nvlist_lookup_uint32(args
, "offset", &offset
)) != 0) {
1703 topo_mod_dprintf(mod
, "Failed to lookup 'offset' arg (%s)\n",
1705 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1707 if ((ret
= nvlist_lookup_uint32(args
, "nparams", &nparams
)) != 0) {
1708 topo_mod_dprintf(mod
, "Failed to lookup 'nparams' arg (%s)\n",
1710 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1712 if (nvlist_lookup_string_array(args
, "format", &fmtarr
, &nelems
) != 0) {
1713 topo_mod_dprintf(mod
, "Failed to lookup 'format' arg (%s)\n",
1715 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1718 if ((entity_refs
= topo_mod_alloc(mod
, (nelems
* sizeof (char *))))
1720 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1722 if (topo_node_flags(node
) & TOPO_NODE_FACILITY
)
1723 refnode
= topo_node_parent(node
);
1727 for (int i
= 0; i
< nelems
; i
++) {
1730 /* LINTED: E_SEC_PRINTF_VAR_FMT */
1731 (void) snprintf(buf
, BUFSZ
, fmtarr
[i
],
1732 (topo_node_instance(refnode
) + offset
));
1735 inst1
= topo_node_instance(topo_node_parent(refnode
))
1737 inst2
= topo_node_instance(refnode
) + offset
;
1738 /* LINTED: E_SEC_PRINTF_VAR_FMT */
1739 (void) snprintf(buf
, BUFSZ
, fmtarr
[i
], inst1
, inst2
);
1742 topo_mod_dprintf(mod
, "Invalid 'nparams' argval (%d)\n",
1744 strarr_free(mod
, entity_refs
, nelems
);
1745 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1747 entity_refs
[i
] = topo_mod_strdup(mod
, buf
);
1749 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
1750 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, "entity_ref") != 0 ||
1751 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
,
1752 TOPO_TYPE_STRING_ARRAY
) != 0 ||
1753 nvlist_add_string_array(nvl
, TOPO_PROP_VAL_VAL
, entity_refs
,
1756 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
1757 strarr_free(mod
, entity_refs
, nelems
);
1759 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1761 strarr_free(mod
, entity_refs
, nelems
);
1769 dimm_ipmi_entity(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
1770 nvlist_t
*in
, nvlist_t
**out
)
1772 char **fmtarr
, **entity_refs
, buf
[BUFSZ
];
1773 tnode_t
*chip
, *dimm
;
1777 nvlist_t
*args
, *nvl
;
1779 if ((ret
= nvlist_lookup_nvlist(in
, TOPO_PROP_ARGS
, &args
)) != 0) {
1780 topo_mod_dprintf(mod
, "Failed to lookup 'args' list (%s)\n",
1782 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1784 if ((ret
= nvlist_lookup_uint32(args
, "offset", &offset
)) != 0) {
1785 topo_mod_dprintf(mod
, "Failed to lookup 'offset' arg (%s)\n",
1787 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1789 if (nvlist_lookup_string_array(args
, "format", &fmtarr
, &nelems
) != 0) {
1790 topo_mod_dprintf(mod
, "Failed to lookup 'format' arg (%s)\n",
1792 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1795 if ((entity_refs
= topo_mod_alloc(mod
, (nelems
* sizeof (char *))))
1797 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1799 if (topo_node_flags(node
) & TOPO_NODE_FACILITY
)
1800 dimm
= topo_node_parent(node
);
1804 chip
= topo_node_parent(topo_node_parent(dimm
));
1806 for (int i
= 0; i
< nelems
; i
++) {
1807 /* LINTED: E_SEC_PRINTF_VAR_FMT */
1808 (void) snprintf(buf
, BUFSZ
, fmtarr
[i
], topo_node_instance(chip
),
1809 (topo_node_instance(dimm
) + offset
));
1810 entity_refs
[i
] = topo_mod_strdup(mod
, buf
);
1813 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
1814 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, "entity_ref") != 0 ||
1815 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
,
1816 TOPO_TYPE_STRING_ARRAY
) != 0 ||
1817 nvlist_add_string_array(nvl
, TOPO_PROP_VAL_VAL
, entity_refs
, nelems
)
1819 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
1820 strarr_free(mod
, entity_refs
, nelems
);
1822 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1824 strarr_free(mod
, entity_refs
, nelems
);
1832 cs_ipmi_entity(topo_mod_t
*mod
, tnode_t
*node
, topo_version_t vers
,
1833 nvlist_t
*in
, nvlist_t
**out
)
1835 char **fmtarr
, **entity_refs
, buf
[BUFSZ
];
1836 tnode_t
*chip
, *chan
, *cs
;
1840 nvlist_t
*args
, *nvl
;
1842 if ((ret
= nvlist_lookup_nvlist(in
, TOPO_PROP_ARGS
, &args
)) != 0) {
1843 topo_mod_dprintf(mod
, "Failed to lookup 'args' list (%s)\n",
1845 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1847 if ((ret
= nvlist_lookup_uint32(args
, "offset", &offset
)) != 0) {
1848 topo_mod_dprintf(mod
, "Failed to lookup 'offset' arg (%s)\n",
1850 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1852 if (nvlist_lookup_string_array(args
, "format", &fmtarr
, &nelems
) != 0) {
1853 topo_mod_dprintf(mod
, "Failed to lookup 'format' arg (%s)\n",
1855 return (topo_mod_seterrno(mod
, EMOD_NVL_INVAL
));
1858 if ((entity_refs
= topo_mod_alloc(mod
, (nelems
* sizeof (char *))))
1860 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1862 if (topo_node_flags(node
) & TOPO_NODE_FACILITY
) {
1863 cs
= topo_node_parent(node
);
1864 chip
= topo_node_parent(topo_node_parent(topo_node_parent(cs
)));
1865 chan
= topo_node_parent(cs
);
1867 dimm_num
= topo_node_instance(cs
) - (topo_node_instance(cs
) % 2)
1868 + topo_node_instance(cs
) + offset
;
1871 chip
= topo_node_parent(topo_node_parent(topo_node_parent(cs
)));
1872 chan
= topo_node_parent(cs
);
1874 dimm_num
= topo_node_instance(cs
) - (topo_node_instance(cs
) % 2)
1875 + topo_node_instance(chan
) + offset
;
1878 for (int i
= 0; i
< nelems
; i
++) {
1879 /* LINTED: E_SEC_PRINTF_VAR_FMT */
1880 (void) snprintf(buf
, BUFSZ
, fmtarr
[i
], topo_node_instance(chip
),
1882 entity_refs
[i
] = topo_mod_strdup(mod
, buf
);
1885 if (topo_mod_nvalloc(mod
, &nvl
, NV_UNIQUE_NAME
) != 0 ||
1886 nvlist_add_string(nvl
, TOPO_PROP_VAL_NAME
, "entity_ref") != 0 ||
1887 nvlist_add_uint32(nvl
, TOPO_PROP_VAL_TYPE
,
1888 TOPO_TYPE_STRING_ARRAY
) != 0 ||
1889 nvlist_add_string_array(nvl
, TOPO_PROP_VAL_VAL
, entity_refs
, nelems
)
1891 topo_mod_dprintf(mod
, "Failed to allocate 'out' nvlist\n");
1892 strarr_free(mod
, entity_refs
, nelems
);
1894 return (topo_mod_seterrno(mod
, EMOD_NOMEM
));
1896 strarr_free(mod
, entity_refs
, nelems
);
1904 fac_prov_ipmi_enum(topo_mod_t
*mod
, tnode_t
*rnode
, const char *name
,
1905 topo_instance_t min
, topo_instance_t max
, void *arg
, void *unused
)
1907 topo_pgroup_info_t pgi
;
1910 if (topo_node_flags(rnode
) == TOPO_NODE_DEFAULT
) {
1911 pgi
.tpi_name
= TOPO_PGROUP_IPMI
;
1912 pgi
.tpi_namestab
= TOPO_STABILITY_PRIVATE
;
1913 pgi
.tpi_datastab
= TOPO_STABILITY_PRIVATE
;
1914 pgi
.tpi_version
= 1;
1915 if (topo_pgroup_create(rnode
, &pgi
, &err
) != 0) {
1916 if (err
!= ETOPO_PROP_DEFD
) {
1917 topo_mod_dprintf(mod
,
1918 "pgroups create failure: %s\n",
1919 topo_strerror(err
));
1923 if (topo_method_register(mod
, rnode
, ipmi_node_methods
) != 0) {
1924 topo_mod_dprintf(mod
, "fac_prov_ipmi_enum: "
1925 "topo_method_register() failed: %s",
1926 topo_mod_errmsg(mod
));
1930 if (topo_method_register(mod
, rnode
, ipmi_fac_methods
) != 0) {
1931 topo_mod_dprintf(mod
, "fac_prov_ipmi_enum: "
1932 "topo_method_register() failed: %s",
1933 topo_mod_errmsg(mod
));