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 2008 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 <unistd.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <strings.h> 33 #include <limits.h> 34 #include <alloca.h> 35 #include <errno.h> 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> 42 #include <libipmi.h> 43 44 #define BUFSZ 128 45 #define TOPO_PGROUP_IPMI "ipmi" 46 47 #define THUMPER_PRESENT_LED_MASK 0x01 48 #define THUMPER_SERVICE_LED_MASK 0x02 49 #define THUMPER_OK2RM_LED_MASK 0x08 50 51 /* 52 * The largest possible SDR ID length is 2^5+1 53 */ 54 #define MAX_ID_LEN 33 55 56 #define TOPO_METH_IPMI_READING_VERSION 0 57 #define TOPO_METH_IPMI_STATE_VERSION 0 58 #define TOPO_METH_IPMI_MODE_VERSION 0 59 #define TOPO_METH_THUMPER_LOCATE_VERSION 0 60 #define TOPO_METH_THUMPER_MODE_VERSION 0 61 #define TOPO_METH_IPMI_ENTITY_VERSION 0 62 #define TOPO_METH_DIMM_IPMI_ENTITY_VERSION 0 63 64 static int fac_prov_ipmi_enum(topo_mod_t *, tnode_t *, const char *, 65 topo_instance_t, topo_instance_t, void *, void *); 66 67 /* 68 * IPMI facility provider methods 69 */ 70 static int ipmi_sensor_enum(topo_mod_t *, tnode_t *, topo_version_t, 71 nvlist_t *, nvlist_t **); 72 static int ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 73 nvlist_t **); 74 static int dimm_ipmi_entity(topo_mod_t *, tnode_t *, topo_version_t, nvlist_t *, 75 nvlist_t **); 76 static int ipmi_sensor_reading(topo_mod_t *, tnode_t *, topo_version_t, 77 nvlist_t *, nvlist_t **); 78 static int ipmi_sensor_state(topo_mod_t *, tnode_t *, topo_version_t, 79 nvlist_t *, nvlist_t **); 80 static int ipmi_indicator_mode(topo_mod_t *, tnode_t *, topo_version_t, 81 nvlist_t *, nvlist_t **); 82 static int thumper_locate_mode(topo_mod_t *, tnode_t *, topo_version_t, 83 nvlist_t *, nvlist_t **); 84 static int thumper_indicator_mode(topo_mod_t *, tnode_t *, topo_version_t, 85 nvlist_t *, nvlist_t **); 86 87 const topo_modops_t ipmi_ops = { fac_prov_ipmi_enum, NULL }; 88 89 const topo_modinfo_t ipmi_info = 90 { "IPMI facility provider", FM_FMRI_SCHEME_HC, TOPO_VERSION, 91 &ipmi_ops }; 92 93 static const topo_method_t ipmi_node_methods[] = { 94 { TOPO_METH_FAC_ENUM, TOPO_METH_FAC_ENUM_DESC, 0, 95 TOPO_STABILITY_INTERNAL, ipmi_sensor_enum }, 96 { TOPO_METH_IPMI_ENTITY, TOPO_PROP_METH_DESC, 97 TOPO_METH_IPMI_ENTITY_VERSION, 98 TOPO_STABILITY_INTERNAL, ipmi_entity }, 99 { "dimm_ipmi_entity", TOPO_PROP_METH_DESC, 100 TOPO_METH_DIMM_IPMI_ENTITY_VERSION, 101 TOPO_STABILITY_INTERNAL, dimm_ipmi_entity }, 102 { NULL } 103 }; 104 105 static const topo_method_t ipmi_fac_methods[] = { 106 { "ipmi_sensor_reading", TOPO_PROP_METH_DESC, 107 TOPO_METH_IPMI_READING_VERSION, 108 TOPO_STABILITY_INTERNAL, ipmi_sensor_reading }, 109 { "ipmi_sensor_state", TOPO_PROP_METH_DESC, 110 TOPO_METH_IPMI_STATE_VERSION, 111 TOPO_STABILITY_INTERNAL, ipmi_sensor_state }, 112 { "ipmi_indicator_mode", TOPO_PROP_METH_DESC, 113 TOPO_METH_IPMI_MODE_VERSION, 114 TOPO_STABILITY_INTERNAL, ipmi_indicator_mode }, 115 { "thumper_locate_mode", TOPO_PROP_METH_DESC, 116 TOPO_METH_THUMPER_LOCATE_VERSION, 117 TOPO_STABILITY_INTERNAL, thumper_locate_mode }, 118 { "thumper_indicator_mode", TOPO_PROP_METH_DESC, 119 TOPO_METH_THUMPER_MODE_VERSION, 120 TOPO_STABILITY_INTERNAL, thumper_indicator_mode }, 121 { TOPO_METH_IPMI_ENTITY, TOPO_PROP_METH_DESC, 122 TOPO_METH_IPMI_ENTITY_VERSION, 123 TOPO_STABILITY_INTERNAL, ipmi_entity }, 124 { "dimm_ipmi_entity", TOPO_PROP_METH_DESC, 125 TOPO_METH_DIMM_IPMI_ENTITY_VERSION, 126 TOPO_STABILITY_INTERNAL, dimm_ipmi_entity }, 127 { NULL } 128 }; 129 130 struct entity_info { 131 uint32_t ei_id; 132 uint32_t ei_inst; 133 topo_mod_t *ei_mod; 134 tnode_t *ei_node; 135 }; 136 137 struct sensor_data { 138 char sd_entity_ref[MAX_ID_LEN]; 139 uint8_t sd_units; 140 uint32_t sd_stype; 141 uint32_t sd_rtype; 142 char *sd_class; 143 }; 144 145 /*ARGSUSED*/ 146 int 147 _topo_init(topo_mod_t *mod, topo_version_t version) 148 { 149 if (getenv("TOPOFACIPMIDEBUG") != NULL) 150 topo_mod_setdebug(mod); 151 152 return (topo_mod_register(mod, &ipmi_info, TOPO_VERSION)); 153 } 154 155 void 156 _topo_fini(topo_mod_t *mod) 157 { 158 topo_mod_unregister(mod); 159 } 160 161 static char * 162 get_fmtstr(topo_mod_t *mod, nvlist_t *in) 163 { 164 char *fmtstr; 165 nvlist_t *args; 166 167 if (nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args) != 0) { 168 topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n", 169 strerror(errno)); 170 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL); 171 return (NULL); 172 } 173 if (nvlist_lookup_string(args, "format", &fmtstr) != 0) { 174 topo_mod_dprintf(mod, "Failed to lookup 'format' arg (%s)\n", 175 strerror(errno)); 176 (void) topo_mod_seterrno(mod, EMOD_NVL_INVAL); 177 return (NULL); 178 } 179 return (fmtstr); 180 } 181 182 /*ARGSUSED*/ 183 static int 184 ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 185 nvlist_t *in, nvlist_t **out) 186 { 187 char *entity_ref; 188 ipmi_sdr_t *sdr = NULL; 189 ipmi_sensor_reading_t *reading; 190 ipmi_handle_t *hdl; 191 int err; 192 uint8_t sensor_num; 193 ipmi_sdr_full_sensor_t *fsensor; 194 ipmi_sdr_compact_sensor_t *csensor; 195 nvlist_t *nvl; 196 197 if (vers > TOPO_METH_IPMI_STATE_VERSION) 198 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); 199 200 if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", 201 &entity_ref, &err) != 0) { 202 topo_mod_dprintf(mod, "Failed to lookup entity_ref property " 203 "(%s)", topo_strerror(err)); 204 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 205 } 206 207 if ((hdl = topo_mod_ipmi(mod)) == NULL) { 208 topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); 209 topo_mod_strfree(mod, entity_ref); 210 return (-1); 211 } 212 213 if ((sdr = ipmi_sdr_lookup(hdl, entity_ref)) == NULL) { 214 topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", 215 entity_ref, ipmi_errmsg(hdl)); 216 topo_mod_strfree(mod, entity_ref); 217 return (-1); 218 } 219 220 switch (sdr->is_type) { 221 case IPMI_SDR_TYPE_FULL_SENSOR: 222 fsensor = (ipmi_sdr_full_sensor_t *)sdr->is_record; 223 sensor_num = fsensor->is_fs_number; 224 break; 225 case IPMI_SDR_TYPE_COMPACT_SENSOR: 226 csensor = (ipmi_sdr_compact_sensor_t *)sdr->is_record; 227 sensor_num = csensor->is_cs_number; 228 break; 229 default: 230 topo_mod_dprintf(mod, "%s does not refer to a full or " 231 "compact SDR\n", entity_ref); 232 topo_mod_strfree(mod, entity_ref); 233 return (-1); 234 } 235 if ((reading = ipmi_get_sensor_reading(hdl, sensor_num)) 236 == NULL) { 237 topo_mod_dprintf(mod, "Failed to get sensor reading for sensor " 238 "%s, sensor_num=%d (%s)\n", entity_ref, sensor_num, 239 ipmi_errmsg(hdl)); 240 topo_mod_strfree(mod, entity_ref); 241 return (-1); 242 } 243 topo_mod_strfree(mod, entity_ref); 244 245 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || 246 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, 247 TOPO_SENSOR_STATE) != 0 || 248 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || 249 nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, reading->isr_state) 250 != 0) { 251 topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); 252 nvlist_free(nvl); 253 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 254 } 255 *out = nvl; 256 257 return (0); 258 } 259 260 /*ARGSUSED*/ 261 static int 262 ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 263 nvlist_t *in, nvlist_t **out) 264 { 265 char *entity_ref, reading_str[BUFSZ]; 266 int err = 0; 267 ipmi_sdr_full_sensor_t *sensor; 268 ipmi_sensor_reading_t *reading; 269 double conv_reading; 270 ipmi_handle_t *hdl; 271 nvlist_t *nvl; 272 273 if (vers > TOPO_METH_IPMI_READING_VERSION) 274 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); 275 276 if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", 277 &entity_ref, &err) != 0) { 278 topo_mod_dprintf(mod, "Failed to lookup entity_ref property " 279 "(%s)", topo_strerror(err)); 280 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 281 } 282 283 if ((hdl = topo_mod_ipmi(mod)) == NULL) { 284 topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); 285 topo_mod_strfree(mod, entity_ref); 286 return (-1); 287 } 288 289 if ((sensor = ipmi_sdr_lookup_full_sensor(hdl, entity_ref)) 290 == NULL) { 291 topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", 292 entity_ref, ipmi_errmsg(hdl)); 293 topo_mod_strfree(mod, entity_ref); 294 return (-1); 295 } 296 297 if ((reading = ipmi_get_sensor_reading(hdl, sensor->is_fs_number)) 298 == NULL) { 299 topo_mod_dprintf(mod, "Failed to get sensor reading for sensor " 300 "%s, sensor_num=%d (%s)\n", entity_ref, 301 sensor->is_fs_number, ipmi_errmsg(hdl)); 302 topo_mod_strfree(mod, entity_ref); 303 return (-1); 304 } 305 if (ipmi_sdr_conv_reading(sensor, reading->isr_reading, &conv_reading) 306 != 0) { 307 topo_mod_dprintf(mod, "Failed to convert sensor reading for " 308 "sensor %s (%s)\n", entity_ref, ipmi_errmsg(hdl)); 309 topo_mod_strfree(mod, entity_ref); 310 return (-1); 311 } 312 topo_mod_strfree(mod, entity_ref); 313 314 (void) snprintf(reading_str, BUFSZ, "%f", conv_reading); 315 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || 316 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, 317 TOPO_SENSOR_READING) != 0 || 318 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_DOUBLE) != 0 || 319 nvlist_add_double(nvl, TOPO_PROP_VAL_VAL, conv_reading) != 0) { 320 topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); 321 nvlist_free(nvl); 322 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 323 } 324 *out = nvl; 325 326 return (0); 327 } 328 329 static int 330 ipmi_indicator_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 331 nvlist_t *in, nvlist_t **out) 332 { 333 char *entity_ref; 334 ipmi_sdr_generic_locator_t *gdl = NULL; 335 ipmi_handle_t *hdl; 336 int err, ret; 337 uint8_t ledmode; 338 uint32_t mode_in; 339 nvlist_t *pargs, *nvl; 340 341 if (vers > TOPO_METH_IPMI_MODE_VERSION) 342 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); 343 344 /* 345 * Get an IPMI handle and then lookup the generic device locator sensor 346 * data record referenced by the entity_ref prop val 347 */ 348 if ((hdl = topo_mod_ipmi(mod)) == NULL) { 349 topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); 350 return (-1); 351 } 352 353 if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", 354 &entity_ref, &err) != 0) { 355 topo_mod_dprintf(mod, "Failed to lookup entity_ref property " 356 "(%s)", topo_strerror(err)); 357 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 358 } 359 360 if ((gdl = ipmi_sdr_lookup_generic(hdl, entity_ref)) 361 == NULL) { 362 topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", 363 entity_ref, ipmi_errmsg(hdl)); 364 topo_mod_strfree(mod, entity_ref); 365 return (-1); 366 } 367 368 /* 369 * Now look for a private argument list to figure out whether we're 370 * doing a get or a set operation, and then do it. 371 */ 372 if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && 373 nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { 374 /* 375 * Set the LED mode 376 */ 377 if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, 378 &mode_in)) != 0) { 379 topo_mod_dprintf(mod, "Failed to lookup %s nvpair " 380 "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret)); 381 topo_mod_strfree(mod, entity_ref); 382 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 383 } 384 if (mode_in != TOPO_LED_STATE_OFF && 385 mode_in != TOPO_LED_STATE_ON) { 386 topo_mod_dprintf(mod, "Invalid property value: %d\n", 387 mode_in); 388 topo_mod_strfree(mod, entity_ref); 389 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 390 } 391 ledmode = (uint8_t)mode_in; 392 topo_mod_dprintf(mod, "Setting LED mode to %s\n", 393 ledmode ? "ON" : "OFF"); 394 if (ipmi_sunoem_led_set(hdl, gdl, ledmode) < 0) { 395 topo_mod_dprintf(mod, "Failed to set LED mode for %s " 396 "(%s)\n", entity_ref, ipmi_errmsg(hdl)); 397 topo_mod_strfree(mod, entity_ref); 398 return (-1); 399 } 400 } else { 401 /* 402 * Get the LED mode 403 */ 404 topo_mod_dprintf(mod, "Getting LED mode\n"); 405 if (ipmi_sunoem_led_get(hdl, gdl, &ledmode) < 0) { 406 topo_mod_dprintf(mod, "Failed to get LED mode for %s " 407 "(%s)\n", entity_ref, ipmi_errmsg(hdl)); 408 topo_mod_strfree(mod, entity_ref); 409 return (-1); 410 } 411 } 412 topo_mod_strfree(mod, entity_ref); 413 414 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || 415 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || 416 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || 417 nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { 418 topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); 419 nvlist_free(nvl); 420 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 421 } 422 *out = nvl; 423 424 return (0); 425 } 426 427 /* 428 * On thumper platforms these is no seperate locate LED for the drive bays. 429 * Therefore we simulate a locate LED by blinking the ok2rm LED. 430 */ 431 static int 432 thumper_locate_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 433 nvlist_t *in, nvlist_t **out) 434 { 435 char *entity_ref; 436 ipmi_sdr_generic_locator_t *gdl = NULL; 437 ipmi_handle_t *hdl; 438 int err, ret; 439 uint8_t ledmode; 440 uint32_t mode_in; 441 nvlist_t *pargs, *nvl; 442 443 if (vers > TOPO_METH_THUMPER_LOCATE_VERSION) 444 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); 445 446 /* 447 * Get an IPMI handle and then lookup the generic device locator sensor 448 * data record referenced by the entity_ref prop val 449 */ 450 if ((hdl = topo_mod_ipmi(mod)) == NULL) { 451 topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); 452 return (-1); 453 } 454 455 if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", 456 &entity_ref, &err) != 0) { 457 topo_mod_dprintf(mod, "Failed to lookup entity_ref property " 458 "(%s)", topo_strerror(err)); 459 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 460 } 461 462 if ((gdl = ipmi_sdr_lookup_generic(hdl, entity_ref)) 463 == NULL) { 464 topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", 465 entity_ref, ipmi_errmsg(hdl)); 466 topo_mod_strfree(mod, entity_ref); 467 return (-1); 468 } 469 470 /* 471 * Now look for a private argument list to figure out whether we're 472 * doing a get or a set operation, and then do it. 473 */ 474 if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && 475 nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { 476 /* 477 * Set the LED mode 478 */ 479 if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, 480 &mode_in)) != 0) { 481 topo_mod_dprintf(mod, "Failed to lookup %s nvpair " 482 "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret)); 483 topo_mod_strfree(mod, entity_ref); 484 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 485 } 486 if (mode_in != TOPO_LED_STATE_OFF && 487 mode_in != TOPO_LED_STATE_ON) { 488 topo_mod_dprintf(mod, "Invalid property value: %d\n", 489 mode_in); 490 topo_mod_strfree(mod, entity_ref); 491 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 492 } 493 if (mode_in == TOPO_LED_STATE_ON) 494 ledmode = IPMI_SUNOEM_LED_MODE_FAST; 495 else 496 ledmode = (uint8_t)mode_in; 497 if (ipmi_sunoem_led_set(hdl, gdl, ledmode) < 0) { 498 topo_mod_dprintf(mod, "Failed to set LED mode for %s " 499 "(%s)\n", entity_ref, ipmi_errmsg(hdl)); 500 topo_mod_strfree(mod, entity_ref); 501 return (-1); 502 } 503 } else { 504 /* 505 * Get the LED mode 506 */ 507 if (ipmi_sunoem_led_get(hdl, gdl, &ledmode) < 0) { 508 topo_mod_dprintf(mod, "Failed to get LED mode for %s " 509 "(%s)\n", entity_ref, ipmi_errmsg(hdl)); 510 topo_mod_strfree(mod, entity_ref); 511 return (-1); 512 } 513 } 514 topo_mod_strfree(mod, entity_ref); 515 516 if (ledmode == IPMI_SUNOEM_LED_MODE_FAST) 517 ledmode = TOPO_LED_STATE_ON; 518 else 519 ledmode = TOPO_LED_STATE_OFF; 520 521 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || 522 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || 523 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || 524 nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { 525 topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); 526 nvlist_free(nvl); 527 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 528 } 529 *out = nvl; 530 531 return (0); 532 } 533 534 535 /* 536 * This is a method for the "mode" property that is specific for the drive bay 537 * LED's on thumper platforms. On thumper, the drive bay LED's are manipulated 538 * by asserting the right state bits in the hdd#.state compact SDR. 539 */ 540 static int 541 thumper_indicator_mode(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 542 nvlist_t *in, nvlist_t **out) 543 { 544 char *entity_ref; 545 ipmi_sdr_compact_sensor_t *cs = NULL; 546 ipmi_handle_t *hdl; 547 int err, ret; 548 uint32_t mask, type, ledmode; 549 nvlist_t *pargs, *nvl; 550 551 if (vers > TOPO_METH_THUMPER_MODE_VERSION) 552 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); 553 554 /* 555 * Figure out which sensor state mask to use based on the indicator 556 * node's type prop val 557 */ 558 if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE, 559 &type, &err) != 0) { 560 topo_mod_dprintf(mod, "Failed to lookup %s property " 561 "(%s)", TOPO_FACILITY_TYPE, topo_strerror(err)); 562 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 563 } 564 switch (type) { 565 case (TOPO_LED_TYPE_SERVICE): 566 mask = THUMPER_SERVICE_LED_MASK; 567 break; 568 case (TOPO_LED_TYPE_PRESENT): 569 mask = THUMPER_PRESENT_LED_MASK; 570 break; 571 case (TOPO_LED_TYPE_OK2RM): 572 mask = THUMPER_OK2RM_LED_MASK; 573 break; 574 default: 575 topo_mod_dprintf(mod, "Invalid LED type: 0x%x\n", type); 576 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 577 } 578 579 /* 580 * Get an IPMI handle and then lookup the compact sensor data record 581 * referenced by the entity_ref prop val 582 */ 583 if ((hdl = topo_mod_ipmi(mod)) == NULL) { 584 topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); 585 return (-1); 586 } 587 588 if (topo_prop_get_string(node, TOPO_PGROUP_FACILITY, "entity_ref", 589 &entity_ref, &err) != 0) { 590 topo_mod_dprintf(mod, "Failed to lookup entity_ref property " 591 "(%s)", topo_strerror(err)); 592 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 593 } 594 595 if ((cs = ipmi_sdr_lookup_compact_sensor(hdl, entity_ref)) 596 == NULL) { 597 topo_mod_dprintf(mod, "Failed to lookup SDR for %s (%s)\n", 598 entity_ref, ipmi_errmsg(hdl)); 599 topo_mod_strfree(mod, entity_ref); 600 return (-1); 601 } 602 603 /* 604 * Now lookup the propmethod argument list and figure out whether we're 605 * doing a get or a set operation, and then do it. 606 */ 607 if ((nvlist_lookup_nvlist(in, TOPO_PROP_PARGS, &pargs) == 0) && 608 nvlist_exists(pargs, TOPO_PROP_VAL_VAL)) { 609 /* 610 * Set the LED mode 611 */ 612 ipmi_set_sensor_reading_t sr_out; 613 614 if ((ret = nvlist_lookup_uint32(pargs, TOPO_PROP_VAL_VAL, 615 &ledmode)) != 0) { 616 topo_mod_dprintf(mod, "Failed to lookup %s nvpair " 617 "(%s)\n", TOPO_PROP_VAL_VAL, strerror(ret)); 618 topo_mod_strfree(mod, entity_ref); 619 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 620 } 621 622 if (ledmode == TOPO_LED_STATE_OFF) { 623 sr_out.iss_deassert_state = mask; 624 sr_out.iss_deassrt_op = IPMI_SENSOR_OP_SET; 625 } else if (ledmode == TOPO_LED_STATE_ON) { 626 sr_out.iss_assert_state = mask; 627 sr_out.iss_assert_op = IPMI_SENSOR_OP_SET; 628 } else { 629 topo_mod_dprintf(mod, "Invalid LED mode: %d 0x%x\n", 630 ledmode); 631 topo_mod_strfree(mod, entity_ref); 632 return (-1); 633 } 634 sr_out.iss_id = cs->is_cs_number; 635 topo_mod_dprintf(mod, "Setting LED mode (mask = 0x%x)\n", mask); 636 if (ipmi_set_sensor_reading(hdl, &sr_out) != 0) { 637 topo_mod_dprintf(mod, "Failed to set sensor reading " 638 "for sensor %s (%s)\n", entity_ref, 639 ipmi_errmsg(hdl)); 640 topo_mod_strfree(mod, entity_ref); 641 return (-1); 642 } 643 } else { 644 /* 645 * Get the LED mode 646 */ 647 ipmi_sensor_reading_t *sr_in; 648 649 topo_mod_dprintf(mod, "Getting LED mode\n"); 650 if ((sr_in = ipmi_get_sensor_reading(hdl, cs->is_cs_number)) 651 == NULL) { 652 topo_mod_dprintf(mod, "Failed to get sensor reading " 653 "for sensor %s (sensor num: %d) (error: %s)\n", 654 entity_ref, cs->is_cs_number, ipmi_errmsg(hdl)); 655 topo_mod_strfree(mod, entity_ref); 656 return (-1); 657 } 658 if (sr_in->isr_state & (uint16_t)mask) 659 ledmode = TOPO_LED_STATE_ON; 660 else 661 ledmode = TOPO_LED_STATE_OFF; 662 } 663 topo_mod_strfree(mod, entity_ref); 664 665 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || 666 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, TOPO_LED_MODE) != 0 || 667 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_UINT32) != 0 || 668 nvlist_add_uint32(nvl, TOPO_PROP_VAL_VAL, ledmode) != 0) { 669 topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); 670 nvlist_free(nvl); 671 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 672 } 673 *out = nvl; 674 return (0); 675 } 676 677 static int 678 make_sensor_node(topo_mod_t *mod, tnode_t *pnode, struct sensor_data *sd) 679 { 680 int err, ret; 681 tnode_t *fnode; 682 char *ftype = "sensor"; 683 topo_pgroup_info_t pgi; 684 nvlist_t *arg_nvl = NULL; 685 686 if ((fnode = topo_node_facbind(mod, pnode, sd->sd_entity_ref, 687 ftype)) == NULL) { 688 topo_mod_dprintf(mod, "Failed to bind facility node: %s\n", 689 sd->sd_entity_ref); 690 /* topo errno set */ 691 return (-1); 692 } 693 694 pgi.tpi_name = TOPO_PGROUP_FACILITY; 695 pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; 696 pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; 697 pgi.tpi_version = 1; 698 if (topo_pgroup_create(fnode, &pgi, &err) != 0) { 699 if (err != ETOPO_PROP_DEFD) { 700 topo_mod_dprintf(mod, "pgroups create failure: %s\n", 701 topo_strerror(err)); 702 topo_node_unbind(fnode); 703 return (-1); 704 } 705 } 706 if (topo_method_register(mod, fnode, ipmi_fac_methods) < 0) { 707 topo_mod_dprintf(mod, "make_fac_node: " 708 "failed to register facility methods"); 709 topo_node_unbind(fnode); 710 return (-1); 711 } 712 /* 713 * For both threshold and discrete sensors we set up a propmethod for 714 * getting the sensor state and properties to hold the entity ref, 715 * sensor class and sensor type. 716 * 717 * Additionally, for analog sensors we set up a property method for 718 * getting the converted sensor reading and property for the base 719 * unit type 720 */ 721 if (topo_prop_set_string(fnode, TOPO_PGROUP_FACILITY, "entity_ref", 722 TOPO_PROP_IMMUTABLE, sd->sd_entity_ref, &err) != 0) { 723 topo_mod_dprintf(mod, "Failed to set entity_ref property on " 724 "node: %s=%d (%s)\n", topo_node_name(fnode), 725 topo_node_instance(fnode), topo_strerror(err)); 726 return (-1); 727 } 728 if (topo_prop_set_string(fnode, TOPO_PGROUP_FACILITY, TOPO_SENSOR_CLASS, 729 TOPO_PROP_IMMUTABLE, sd->sd_class, &err) != 0) { 730 topo_mod_dprintf(mod, "Failed to set %s property on node: " 731 "%s=%d (%s)\n", TOPO_SENSOR_CLASS, topo_node_name(fnode), 732 topo_node_instance(fnode), topo_strerror(err)); 733 return (-1); 734 } 735 if (topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY, 736 TOPO_FACILITY_TYPE, TOPO_PROP_IMMUTABLE, sd->sd_stype, &err) != 0) { 737 topo_mod_dprintf(mod, "Failed to set %s property on node: " 738 "%s=%d (%s)\n", TOPO_FACILITY_TYPE, topo_node_name(fnode), 739 topo_node_instance(fnode), topo_strerror(err)); 740 return (-1); 741 } 742 if (topo_mod_nvalloc(mod, &arg_nvl, NV_UNIQUE_NAME) < 0) { 743 topo_node_unbind(fnode); 744 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 745 } 746 747 if ((ret = nvlist_add_string(arg_nvl, "ipmi_entity", sd->sd_entity_ref)) 748 != 0) { 749 topo_mod_dprintf(mod, "Failed build arg nvlist (%s)\n", 750 strerror(ret)); 751 nvlist_free(arg_nvl); 752 return (-1); 753 } 754 755 if (topo_prop_method_register(fnode, TOPO_PGROUP_FACILITY, 756 TOPO_SENSOR_STATE, TOPO_TYPE_UINT32, "ipmi_sensor_state", arg_nvl, 757 &err) != 0) { 758 topo_mod_dprintf(mod, "Failed to register %s propmeth on fac " 759 "node %s (%s)\n", TOPO_SENSOR_STATE, topo_node_name(fnode), 760 topo_strerror(err)); 761 nvlist_free(arg_nvl); 762 return (-1); 763 } 764 765 if (strcmp(sd->sd_class, TOPO_SENSOR_CLASS_THRESHOLD) == 0) { 766 if (topo_prop_method_register(fnode, TOPO_PGROUP_FACILITY, 767 TOPO_SENSOR_READING, TOPO_TYPE_DOUBLE, 768 "ipmi_sensor_reading", arg_nvl, &err) != 0) { 769 topo_mod_dprintf(mod, "Failed to register %s propmeth " 770 "on fac node %s (%s)\n", TOPO_SENSOR_READING, 771 topo_node_name(fnode), topo_strerror(err)); 772 nvlist_free(arg_nvl); 773 return (-1); 774 } 775 if (topo_prop_set_uint32(fnode, TOPO_PGROUP_FACILITY, 776 TOPO_SENSOR_UNITS, TOPO_PROP_IMMUTABLE, sd->sd_units, &err) 777 != 0) { 778 topo_mod_dprintf(mod, "Failed to set units property on " 779 "node: %s (%s)\n", topo_node_name(fnode), 780 topo_strerror(err)); 781 nvlist_free(arg_nvl); 782 return (-1); 783 } 784 } 785 nvlist_free(arg_nvl); 786 return (0); 787 } 788 789 /* ARGSUSED */ 790 static int 791 sdr_callback(ipmi_handle_t *hdl, const char *id, ipmi_sdr_t *sdr, void *data) 792 { 793 uint8_t sensor_entity, sensor_inst; 794 int sensor_idlen; 795 ipmi_sdr_full_sensor_t *f_sensor = NULL; 796 ipmi_sdr_compact_sensor_t *c_sensor = NULL; 797 struct sensor_data sd; 798 struct entity_info *ei = (struct entity_info *)data; 799 800 switch (sdr->is_type) { 801 case IPMI_SDR_TYPE_FULL_SENSOR: 802 f_sensor = 803 (ipmi_sdr_full_sensor_t *)sdr->is_record; 804 sensor_entity = f_sensor->is_fs_entity_id; 805 sensor_inst = f_sensor->is_fs_entity_instance; 806 sensor_idlen = f_sensor->is_fs_idlen; 807 (void) strncpy(sd.sd_entity_ref, 808 f_sensor->is_fs_idstring, 809 f_sensor->is_fs_idlen); 810 sd.sd_entity_ref[sensor_idlen] = '\0'; 811 sd.sd_class = TOPO_SENSOR_CLASS_THRESHOLD; 812 sd.sd_units = f_sensor->is_fs_unit2; 813 sd.sd_stype = f_sensor->is_fs_type; 814 sd.sd_rtype = f_sensor->is_fs_reading_type; 815 break; 816 case IPMI_SDR_TYPE_COMPACT_SENSOR: 817 c_sensor = 818 (ipmi_sdr_compact_sensor_t *)sdr->is_record; 819 sensor_entity = c_sensor->is_cs_entity_id; 820 sensor_inst = c_sensor->is_cs_entity_instance; 821 sensor_idlen = c_sensor->is_cs_idlen; 822 (void) strncpy(sd.sd_entity_ref, 823 c_sensor->is_cs_idstring, 824 sensor_idlen); 825 sd.sd_entity_ref[sensor_idlen] = '\0'; 826 sd.sd_class = TOPO_SENSOR_CLASS_DISCRETE; 827 sd.sd_units = c_sensor->is_cs_unit2; 828 sd.sd_stype = c_sensor->is_cs_type; 829 sd.sd_rtype = c_sensor->is_cs_reading_type; 830 break; 831 default: 832 return (0); 833 } 834 /* 835 * We offset the threshold and generic sensor reading types by 0x100 836 */ 837 if (sd.sd_rtype >= 0x1 && sd.sd_rtype <= 0xc) 838 sd.sd_stype = sd.sd_rtype + 0x100; 839 840 if ((sensor_entity == ei->ei_id) && (sensor_inst == ei->ei_inst)) 841 if (make_sensor_node(ei->ei_mod, ei->ei_node, &sd) != 0) { 842 topo_mod_dprintf(ei->ei_mod, "Failed to create sensor " 843 "node for %s\n", sd.sd_entity_ref); 844 if (topo_mod_errno(ei->ei_mod) != EMOD_NODE_DUP) 845 return (-1); 846 } 847 return (0); 848 } 849 850 /* ARGSUSED */ 851 static int 852 ipmi_sensor_enum(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 853 nvlist_t *in, nvlist_t **out) 854 { 855 char *entity_ref; 856 int err; 857 struct entity_info ei; 858 ipmi_sdr_t *ref_sdr; 859 ipmi_handle_t *hdl; 860 ipmi_sdr_full_sensor_t *fsensor; 861 ipmi_sdr_compact_sensor_t *csensor; 862 ipmi_sdr_fru_locator_t *floc; 863 ipmi_sdr_generic_locator_t *gloc; 864 865 if ((hdl = topo_mod_ipmi(mod)) == NULL) { 866 topo_mod_dprintf(mod, "Failed to get IPMI handle\n"); 867 return (-1); 868 } 869 870 /* 871 * Use the entity ref to lookup the SDR, which will have the entity ID 872 * and instance. 873 */ 874 if (topo_prop_get_string(node, TOPO_PGROUP_IPMI, 875 "entity_ref", &entity_ref, &err) != 0) { 876 topo_mod_dprintf(mod, "Failed to lookup entity_ref " 877 "property (%s)\n", topo_strerror(err)); 878 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 879 } 880 881 topo_mod_dprintf(mod, "Looking up SDR for %s ...\n", 882 entity_ref); 883 if ((ref_sdr = ipmi_sdr_lookup(hdl, entity_ref)) == NULL) { 884 topo_mod_dprintf(mod, "Failed to lookup SDR (%s)\n", 885 ipmi_errmsg(hdl)); 886 topo_mod_strfree(mod, entity_ref); 887 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 888 } 889 topo_mod_strfree(mod, entity_ref); 890 891 switch (ref_sdr->is_type) { 892 case IPMI_SDR_TYPE_FULL_SENSOR: 893 fsensor = (ipmi_sdr_full_sensor_t *)ref_sdr->is_record; 894 ei.ei_id = fsensor->is_fs_entity_id; 895 ei.ei_inst = fsensor->is_fs_entity_instance; 896 break; 897 case IPMI_SDR_TYPE_COMPACT_SENSOR: 898 csensor 899 = (ipmi_sdr_compact_sensor_t *)ref_sdr->is_record; 900 ei.ei_id = csensor->is_cs_entity_id; 901 ei.ei_inst = csensor->is_cs_entity_instance; 902 break; 903 case IPMI_SDR_TYPE_FRU_LOCATOR: 904 floc = (ipmi_sdr_fru_locator_t *)ref_sdr->is_record; 905 ei.ei_id = floc->is_fl_entity; 906 ei.ei_inst = floc->is_fl_instance; 907 break; 908 case IPMI_SDR_TYPE_GENERIC_LOCATOR: 909 gloc = (ipmi_sdr_generic_locator_t *)ref_sdr->is_record; 910 ei.ei_id = gloc->is_gl_entity; 911 ei.ei_inst = gloc->is_gl_instance; 912 break; 913 default: 914 topo_mod_dprintf(mod, "Failed to determine entity id " 915 "and instance\n", ipmi_errmsg(hdl)); 916 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 917 } 918 topo_mod_dprintf(mod, "Entity ID = 0x%x, Entity Instance = 0x%x\n", 919 ei.ei_id, ei.ei_inst); 920 921 ei.ei_node = node; 922 ei.ei_mod = mod; 923 924 /* 925 * Now iterate through all of the full and compact sensor data records 926 * and create a sensor facility node for each record that matches our 927 * entity ID and instance 928 */ 929 if (ipmi_sdr_iter(hdl, sdr_callback, &ei) != 0) { 930 topo_mod_dprintf(mod, "ipmi_sdr_iter() failed\n"); 931 return (-1); 932 } 933 return (0); 934 } 935 936 static int 937 ipmi_entity(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 938 nvlist_t *in, nvlist_t **out) 939 { 940 char *fmtstr, buf[BUFSZ]; 941 tnode_t *refnode; 942 int ret, inst1, inst2; 943 uint32_t offset, nparams; 944 nvlist_t *args, *nvl; 945 946 if (vers > TOPO_METH_IPMI_ENTITY_VERSION) 947 return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); 948 949 if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) { 950 topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n", 951 strerror(ret)); 952 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 953 } 954 if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) { 955 topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n", 956 strerror(ret)); 957 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 958 } 959 if ((ret = nvlist_lookup_uint32(args, "nparams", &nparams)) != 0) { 960 topo_mod_dprintf(mod, "Failed to lookup 'nparams' arg (%s)\n", 961 strerror(ret)); 962 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 963 } 964 965 if ((fmtstr = get_fmtstr(mod, in)) == NULL) { 966 topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n"); 967 /* topo errno already set */ 968 return (-1); 969 } 970 971 if (topo_node_flags(node) & TOPO_NODE_FACILITY) 972 refnode = topo_node_parent(node); 973 else 974 refnode = node; 975 976 switch (nparams) { 977 case 1: 978 /* LINTED: E_SEC_PRINTF_VAR_FMT */ 979 (void) snprintf(buf, BUFSZ, fmtstr, 980 (topo_node_instance(refnode) + offset)); 981 break; 982 case 2: 983 inst1 = topo_node_instance(topo_node_parent(refnode)) + offset; 984 inst2 = topo_node_instance(refnode) + offset; 985 /* LINTED: E_SEC_PRINTF_VAR_FMT */ 986 (void) snprintf(buf, BUFSZ, fmtstr, inst1, inst2); 987 break; 988 default: 989 topo_mod_dprintf(mod, "Invalid 'nparams' argval (%d)\n", 990 nparams); 991 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 992 } 993 994 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || 995 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, "entity_ref") != 0 || 996 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_STRING) != 0 || 997 nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, buf) != 0) { 998 topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); 999 nvlist_free(nvl); 1000 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 1001 } 1002 *out = nvl; 1003 1004 return (0); 1005 } 1006 1007 /* ARGSUSED */ 1008 static int 1009 dimm_ipmi_entity(topo_mod_t *mod, tnode_t *node, topo_version_t vers, 1010 nvlist_t *in, nvlist_t **out) 1011 { 1012 char *fmtstr, buf[BUFSZ]; 1013 tnode_t *chip, *dimm; 1014 int ret; 1015 uint32_t offset; 1016 nvlist_t *args, *nvl; 1017 1018 if ((ret = nvlist_lookup_nvlist(in, TOPO_PROP_ARGS, &args)) != 0) { 1019 topo_mod_dprintf(mod, "Failed to lookup 'args' list (%s)\n", 1020 strerror(ret)); 1021 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 1022 } 1023 if ((ret = nvlist_lookup_uint32(args, "offset", &offset)) != 0) { 1024 topo_mod_dprintf(mod, "Failed to lookup 'offset' arg (%s)\n", 1025 strerror(ret)); 1026 return (topo_mod_seterrno(mod, EMOD_NVL_INVAL)); 1027 } 1028 1029 if ((fmtstr = get_fmtstr(mod, in)) == NULL) { 1030 topo_mod_dprintf(mod, "Failed to retrieve 'format' arg\n"); 1031 /* topo errno already set */ 1032 return (-1); 1033 } 1034 1035 if (topo_node_flags(node) & TOPO_NODE_FACILITY) 1036 dimm = topo_node_parent(node); 1037 else 1038 dimm = node; 1039 1040 chip = topo_node_parent(topo_node_parent(dimm)); 1041 1042 /* LINTED: E_SEC_PRINTF_VAR_FMT */ 1043 (void) snprintf(buf, BUFSZ, fmtstr, topo_node_instance(chip), 1044 (topo_node_instance(dimm) + offset)); 1045 1046 if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0 || 1047 nvlist_add_string(nvl, TOPO_PROP_VAL_NAME, "entity_ref") != 0 || 1048 nvlist_add_uint32(nvl, TOPO_PROP_VAL_TYPE, TOPO_TYPE_STRING) != 0 || 1049 nvlist_add_string(nvl, TOPO_PROP_VAL_VAL, buf) != 0) { 1050 topo_mod_dprintf(mod, "Failed to allocate 'out' nvlist\n"); 1051 nvlist_free(nvl); 1052 return (topo_mod_seterrno(mod, EMOD_NOMEM)); 1053 } 1054 *out = nvl; 1055 1056 return (0); 1057 } 1058 1059 /*ARGSUSED*/ 1060 static int 1061 fac_prov_ipmi_enum(topo_mod_t *mod, tnode_t *rnode, const char *name, 1062 topo_instance_t min, topo_instance_t max, void *arg, void *unused) 1063 { 1064 topo_pgroup_info_t pgi; 1065 int err; 1066 1067 if (topo_node_flags(rnode) == TOPO_NODE_DEFAULT) { 1068 pgi.tpi_name = TOPO_PGROUP_IPMI; 1069 pgi.tpi_namestab = TOPO_STABILITY_PRIVATE; 1070 pgi.tpi_datastab = TOPO_STABILITY_PRIVATE; 1071 pgi.tpi_version = 1; 1072 if (topo_pgroup_create(rnode, &pgi, &err) != 0) { 1073 if (err != ETOPO_PROP_DEFD) { 1074 topo_mod_dprintf(mod, 1075 "pgroups create failure: %s\n", 1076 topo_strerror(err)); 1077 return (-1); 1078 } 1079 } 1080 if (topo_method_register(mod, rnode, ipmi_node_methods) != 0) { 1081 topo_mod_dprintf(mod, "fac_prov_ipmi_enum: " 1082 "topo_method_register() failed: %s", 1083 topo_mod_errmsg(mod)); 1084 return (-1); 1085 } 1086 } else { 1087 if (topo_method_register(mod, rnode, ipmi_fac_methods) != 0) { 1088 topo_mod_dprintf(mod, "fac_prov_ipmi_enum: " 1089 "topo_method_register() failed: %s", 1090 topo_mod_errmsg(mod)); 1091 return (-1); 1092 } 1093 } 1094 return (0); 1095 } 1096