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