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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Daktari platform platform specific environment monitoring policies 31 */ 32 #include <poll.h> 33 #include <syslog.h> 34 #include <unistd.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <errno.h> 38 #include <fcntl.h> 39 #include <strings.h> 40 #include <libintl.h> 41 #include <sys/types.h> 42 #include <sys/param.h> 43 #include <config_admin.h> 44 #include <libdevice.h> 45 #include <picl.h> 46 #include <picltree.h> 47 #include <psvc_objects.h> 48 #include <sys/i2c/clients/i2c_client.h> 49 #include <sys/daktari.h> 50 #include <sys/hpc3130_events.h> 51 #include <assert.h> 52 53 /*LINTLIBRARY*/ 54 55 /* resides in libcfgadm */ 56 extern cfga_err_t config_change_state(cfga_cmd_t, int, char *const *, 57 const char *, struct cfga_confirm *, struct cfga_msg *, char **, 58 cfga_flags_t); 59 /* Local Routine */ 60 static int32_t update_gen_fault_led(psvc_opaque_t, char *); 61 static void shutdown_routine(void); 62 static int32_t update_thresholds(psvc_opaque_t hdlp, char *id, int offset); 63 64 65 #ifdef DEBUG 66 67 static int dak_policy_debug = 0; 68 69 #define D1SYS_ERR(ARGS) if (dak_policy_debug & 0x1) syslog ARGS; 70 #define D2SYS_ERR(ARGS) if (dak_policy_debug & 0x2) syslog ARGS; 71 72 #else 73 74 #define D1SYS_ERR(ARGS) 75 #define D2SYS_ERR(ARGS) 76 77 #endif 78 79 #define I2C_PATH "/devices/pci@9,700000/ebus@1/i2c@1,30" 80 #define I2C_NODE I2C_PATH ":devctl" 81 #define PCF8574 I2C_PATH "/ioexp@0,%x:pcf8574" 82 #define PCF8591 I2C_PATH "/adio@0,%x:port_0" 83 #define FRU I2C_PATH "/fru@0,%x:fru" 84 #define HPC3130_DEV I2C_PATH "/hotplug-controller@0,%2x:port_%1x" 85 #define GEN_FAULT_LED "FSP_GEN_FAULT_LED" 86 #define EMPTY_STRING "EMPTY" 87 #define DEVICE_FAILURE_MSG gettext("WARNING: Device %s failure detected") 88 #define DEVICE_INSERTED_MSG gettext("Device %s inserted") 89 #define DEVICE_REMOVED_MSG gettext("Device %s removed") 90 #define PS_UNPLUGGED_MSG gettext("Device %s unplugged") 91 #define PS_PLUGGED_MSG gettext("Device %s Plugged in") 92 #define DEVICE_OK_MSG gettext("Device %s OK") 93 #define SET_LED_FAILED_MSG \ 94 gettext("Failed to set LED state, id = %s, errno = %d\n") 95 #define GET_PRESENCE_FAILED_MSG \ 96 gettext("Failed to get presence attribute, id = %s, errno = %d\n") 97 #define GET_SENSOR_FAILED_MSG \ 98 gettext("Failed to get sensor value, id = %s, errno = %d\n") 99 #define ADD_PS_MSG \ 100 gettext("WARNING: Only 1 Power Supply in system. ADD a 2nd Power Supply.\n") 101 #define REMOVE_LOAD_MSG \ 102 gettext("WARNING: Power Supply at 95%% current. Remove some load.\n") 103 #define PS_OVER_CURRENT_MSG \ 104 gettext("WARNING: Power Supply overcurrent detected\n") 105 #define DEVICE_UNKNOWN_MSG gettext("Unknown device %s instance %d\n") 106 #define DEVICE_HANDLE_FAIL_MSG \ 107 gettext("Failed to get device handle for %s, errno = %d\n") 108 #define DEVTREE_NODE_CREATE_FAILED \ 109 gettext("psvc PICL plugin: Failed to create node for %s, errno = %d") 110 #define DEVTREE_NODE_DELETE_FAILED \ 111 gettext("psvc PICL plugin: Failed to delete node for %s, errno = %d") 112 #define DISK_FAULT_MSG gettext("%s: Error Reported\n") 113 #define DISK_OK_MSG gettext("%s: Error Cleared\n") 114 #define SET_FANSPEED_FAILED_MSG \ 115 gettext("Failed to set fan speed, id = %s, errno = %d\n") 116 #define GET_ATTR_FRU_FAILED_MSG gettext("Failed psvc_get_attr for FRU info\n") 117 #define NO_FRU_INFO_MSG \ 118 gettext("No FRU Information for %s using default module card\n") 119 120 #define DAKTARI_MAX_PS 3 121 #define DAK_MAX_PS_I_SENSORS 4 122 #define DAK_MAX_DISKS 12 123 #define DAK_MAX_CPU_MOD 4 124 #define DAK_MAX_FAULT_SENSORS 3 125 #define DAK_MAX_FANS 10 126 127 static int co_ps = 0; 128 static char *shutdown_string = "shutdown -y -g 60 -i 5 \"OVERTEMP condition\""; 129 130 typedef struct i2c_hp { 131 int32_t addr[2]; 132 char name[256]; 133 char compatible[256]; 134 } i2c_hp_t; 135 136 typedef struct seg_desc { 137 int32_t segdesc; 138 int16_t segoffset; 139 int16_t seglength; 140 } seg_desc_t; 141 142 static int32_t threshold_names[] = { 143 PSVC_HW_LO_SHUT_ATTR, 144 PSVC_LO_SHUT_ATTR, 145 PSVC_LO_WARN_ATTR, 146 PSVC_NOT_USED, /* LOW MODE which is not used */ 147 PSVC_OPTIMAL_TEMP_ATTR, 148 PSVC_HI_WARN_ATTR, 149 PSVC_HI_SHUT_ATTR, 150 PSVC_HW_HI_SHUT_ATTR 151 }; 152 153 int32_t 154 psvc_MB_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset) 155 { 156 int IO_offset = 0xd; 157 int32_t err; 158 159 err = update_thresholds(hdlp, id, IO_offset); 160 161 return (err); 162 } 163 164 int32_t 165 psvc_IO_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset) 166 { 167 int IO_offset = 0x8; 168 int32_t err; 169 170 err = update_thresholds(hdlp, id, IO_offset); 171 172 return (err); 173 } 174 175 int32_t 176 psvc_DBP_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset) 177 { 178 int IO_offset = 0x7; 179 int32_t err; 180 181 err = update_thresholds(hdlp, id, IO_offset); 182 183 return (err); 184 } 185 186 /* 187 * used to determine if a change of state occured. valid when states 188 * are strings. 189 */ 190 static int8_t 191 change_of_state_str(char *state1, char *check1, char *state2, char *check2) 192 { 193 int change = 0; 194 195 if ((strcmp(state1, check1) == 0) && (strcmp(state2, check2) != 0)) 196 change = 1; 197 if ((strcmp(state1, check1) != 0) && (strcmp(state2, check2) == 0)) 198 change = 1; 199 200 return (change); 201 } 202 203 /* 204 * Update thresholds tries to read the temperature thresholds from the FRU 205 * SEEproms and then updates the thresholds in the object by overriding the 206 * hardcoded thresholds. For Daktari it is an Error if the FRU does not 207 * contain the segment that had the temperature thresholds. 208 */ 209 static int32_t 210 update_thresholds(psvc_opaque_t hdlp, char *id, int offset) 211 { 212 int32_t status = PSVC_SUCCESS; 213 fru_info_t fru_data; 214 char *fru, seg_name[2]; 215 int8_t seg_count, temp_array[8]; 216 int32_t match_count, i, j, seg_desc_start = 0x1806, temp_address; 217 int32_t seg_found, temp; 218 boolean_t present; 219 seg_desc_t segment; 220 221 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 222 if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) 223 return (status); 224 225 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count, 226 PSVC_FRU); 227 if (status == PSVC_FAILURE) 228 return (status); 229 230 for (i = 0; i < match_count; i++) { 231 seg_found = 0; 232 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 233 &fru, PSVC_FRU, i); 234 if (status != PSVC_SUCCESS) 235 return (status); 236 237 fru_data.buf_start = 0x1805; 238 fru_data.buf = (char *)&seg_count; 239 fru_data.read_size = 1; 240 241 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 242 &fru_data); 243 if (status != PSVC_SUCCESS) { 244 return (status); 245 } 246 for (j = 0; (j < seg_count) && (!seg_found); j++) { 247 fru_data.buf_start = seg_desc_start; 248 fru_data.buf = seg_name; 249 fru_data.read_size = 2; 250 251 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 252 &fru_data); 253 254 seg_desc_start = seg_desc_start + 2; 255 fru_data.buf_start = seg_desc_start; 256 fru_data.buf = (char *)&segment; 257 fru_data.read_size = sizeof (seg_desc_t); 258 259 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 260 &fru_data); 261 if (status != PSVC_SUCCESS) { 262 syslog(LOG_ERR, 263 "Failed psvc_get_attr for FRU info\n"); 264 return (status); 265 } 266 seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 267 if (memcmp(seg_name, "SC", 2) == 0) 268 seg_found = 1; 269 } 270 if (seg_found) { 271 temp_address = segment.segoffset + offset; 272 fru_data.buf_start = temp_address; 273 fru_data.buf = (char *)&temp_array; 274 fru_data.read_size = sizeof (temp_array); 275 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 276 &fru_data); 277 if (status != PSVC_SUCCESS) { 278 syslog(LOG_ERR, 279 "Failed psvc_get_attr for FRU info\n"); 280 return (status); 281 } else { 282 for (j = 0; j < sizeof (temp_array); j++) { 283 if (threshold_names[j] == 284 PSVC_NOT_USED) 285 continue; 286 temp = temp_array[j]; 287 status = psvc_set_attr(hdlp, id, 288 threshold_names[j], &temp); 289 if (status != PSVC_SUCCESS) { 290 return (status); 291 } 292 } 293 } 294 } else { 295 syslog(LOG_ERR, "No FRU Information for %s" 296 " using default temperatures\n", id); 297 } 298 } 299 return (status); 300 } 301 302 int32_t 303 psvc_fan_init_speed_0(psvc_opaque_t hdlp, char *id) 304 { 305 int32_t status = PSVC_SUCCESS; 306 boolean_t present; 307 char *control_id; 308 int32_t init_speed = 0; 309 310 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 311 if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) 312 return (status); 313 314 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &control_id, 315 PSVC_FAN_DRIVE_CONTROL, 0); 316 if (status != PSVC_SUCCESS) 317 return (status); 318 319 status = psvc_set_attr(hdlp, control_id, PSVC_CONTROL_VALUE_ATTR, 320 &init_speed); 321 if (status == PSVC_FAILURE) { 322 syslog(LOG_ERR, SET_FANSPEED_FAILED_MSG, control_id, errno); 323 return (status); 324 } 325 326 return (status); 327 } 328 329 int32_t 330 psvc_update_setpoint_0(psvc_opaque_t hdlp, char *id) 331 { 332 int32_t status = PSVC_SUCCESS; 333 char *temp_sensor; 334 int32_t match_count, i, temp; 335 int16_t lowest_temp = 500; 336 boolean_t present; 337 338 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 339 if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) 340 return (status); 341 342 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count, 343 PSVC_DEV_TEMP_SENSOR); 344 if (status == PSVC_FAILURE) 345 return (status); 346 347 for (i = 0; i < match_count; i++) { 348 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 349 &temp_sensor, PSVC_DEV_TEMP_SENSOR, i); 350 if (status != PSVC_SUCCESS) 351 return (status); 352 status = psvc_get_attr(hdlp, temp_sensor, 353 PSVC_OPTIMAL_TEMP_ATTR, &temp); 354 if (status != PSVC_SUCCESS) { 355 syslog(LOG_ERR, "Failed to get Optimal temp for %s\n", 356 temp_sensor); 357 return (status); 358 } 359 if (temp < lowest_temp) 360 lowest_temp = temp; 361 } 362 status = psvc_set_attr(hdlp, id, PSVC_SETPOINT_ATTR, &lowest_temp); 363 if (status == PSVC_FAILURE) { 364 syslog(LOG_ERR, "Failed to change setpoint for %s\n", id); 365 return (status); 366 } 367 return (status); 368 } 369 370 int32_t 371 psvc_remove_missing_nodes_0(psvc_opaque_t hdlp, char *id) 372 { 373 int32_t status = PSVC_SUCCESS; 374 char state[32]; 375 char *physical_dev; 376 int32_t i, device_count; 377 char parent_path[256]; 378 picl_nodehdl_t child_node; 379 boolean_t present; 380 381 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 382 &device_count, PSVC_PHYSICAL_DEVICE); 383 if (status == PSVC_FAILURE) 384 return (status); 385 386 for (i = 0; i < device_count; i++) { 387 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 388 &physical_dev, PSVC_PHYSICAL_DEVICE, i); 389 if (status != PSVC_SUCCESS) 390 return (status); 391 if (strncmp(physical_dev, "LTC1427", 7) == 0) 392 continue; 393 status = psvc_get_attr(hdlp, physical_dev, 394 PSVC_PROBE_RESULT_ATTR, state); 395 if (status != PSVC_SUCCESS) 396 continue; 397 status = psvc_get_attr(hdlp, physical_dev, PSVC_PRESENCE_ATTR, 398 &present); 399 if (status == PSVC_FAILURE) { 400 syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, physical_dev, 401 errno); 402 return (status); 403 } 404 405 if ((strcmp(state, PSVC_ERROR) == 0) && 406 (present == PSVC_PRESENT)) { 407 /* convert name to node, and parent path */ 408 psvcplugin_lookup(physical_dev, parent_path, 409 &child_node); 410 /* Device removed */ 411 ptree_delete_node(child_node); 412 } 413 } 414 return (status); 415 } 416 417 int32_t 418 psvc_check_ps_hotplug_status_0(psvc_opaque_t hdlp, char *id) 419 { 420 char fail_valid_switch_id[PICL_PROPNAMELEN_MAX]; 421 int32_t status = PSVC_SUCCESS; 422 char valid_switch_state[32]; 423 char state[32], fault[32]; 424 int32_t led_count, j; 425 char *led_id; 426 char led_state[32]; 427 boolean_t present; 428 static int8_t hotplug_failed_count = 0; 429 int8_t retry; 430 431 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 432 if (status == PSVC_FAILURE) { 433 syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, id, errno); 434 return (status); 435 } 436 437 if (present == PSVC_ABSENT) { 438 errno = ENODEV; 439 return (PSVC_FAILURE); 440 } 441 442 snprintf(fail_valid_switch_id, sizeof (fail_valid_switch_id), "%s%s", 443 id, "_SENSOR_VALID_SWITCH"); 444 445 retry = 0; 446 do { 447 if (retry) 448 sleep(1); 449 status = psvc_get_attr(hdlp, fail_valid_switch_id, 450 PSVC_STATE_ATTR, valid_switch_state); 451 if (status == PSVC_FAILURE) { 452 if (hotplug_failed_count == 0) { 453 /* 454 * First time the get_attr call failed 455 * set count so that if we fail again 456 * we will know 457 */ 458 hotplug_failed_count = 1; 459 /* 460 * We probably failed because the power 461 * supply was just insterted or removed 462 * before the get_attr call. We then 463 * return from this policy successfully 464 * knowing it will be run again shortly 465 * with the right PS state. 466 */ 467 return (PSVC_SUCCESS); 468 } else { 469 /* 470 * We have failed before and so this 471 * we will consider a hardware problem 472 * and it should be reported 473 */ 474 syslog(LOG_ERR, 475 "Failed getting %s State: ", 476 "ps_hotplug_status_0\n", 477 fail_valid_switch_id); 478 return (status); 479 } 480 } 481 /* 482 * Because we have successfully gotten a value from 483 * the i2c device on the PS we will set the 484 * failed_count to 0 485 */ 486 hotplug_failed_count = 0; 487 488 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state); 489 if (status == PSVC_FAILURE) 490 return (status); 491 retry++; 492 /* 493 * check to see if we need to retry. the conditions are: 494 * 495 * valid_switch_state state retry 496 * -------------------------------------------------- 497 * PSVC_OFF !PSVC_HOTPLUGGED yes 498 * PSVC_ON PSVC_HOTPLUGGED yes 499 * PSVC_OFF PSVC_HOTPLUGGED no 500 * PSVC_ON !PSVC_HOTPLUGGED no 501 */ 502 } while ((retry < PSVC_NUM_OF_RETRIES) && 503 change_of_state_str(valid_switch_state, PSVC_OFF, 504 state, PSVC_HOTPLUGGED)); 505 506 if ((strcmp(valid_switch_state, PSVC_OFF) == 0) && 507 (strcmp(state, PSVC_HOTPLUGGED) != 0)) { 508 strcpy(state, PSVC_HOTPLUGGED); 509 strcpy(fault, PSVC_NO_FAULT); 510 strcpy(led_state, PSVC_LED_OFF); 511 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 512 state); 513 if (status == PSVC_FAILURE) 514 return (status); 515 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 516 &led_count, PSVC_DEV_FAULT_LED); 517 if (status == PSVC_FAILURE) 518 return (status); 519 520 for (j = 0; j < led_count; j++) { 521 522 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 523 &led_id, PSVC_DEV_FAULT_LED, j); 524 if (status != PSVC_SUCCESS) 525 return (status); 526 527 status = psvc_set_attr(hdlp, led_id, 528 PSVC_LED_STATE_ATTR, led_state); 529 if (status != PSVC_SUCCESS) { 530 syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, 531 errno); 532 return (status); 533 } 534 535 } 536 syslog(LOG_ERR, PS_UNPLUGGED_MSG, id); 537 return (status); 538 } 539 540 if ((strcmp(valid_switch_state, PSVC_ON) == 0) && 541 (strcmp(state, PSVC_HOTPLUGGED) == 0)) { 542 strcpy(state, PSVC_OK); 543 strcpy(fault, PSVC_NO_FAULT); 544 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 545 if (status == PSVC_FAILURE) 546 return (status); 547 syslog(LOG_ERR, PS_PLUGGED_MSG, id); 548 } 549 550 return (status); 551 } 552 553 int32_t 554 psvc_ps_overcurrent_check_policy_0(psvc_opaque_t hdlp, char *system) 555 { 556 int32_t status = PSVC_SUCCESS; 557 boolean_t present; 558 static char *sensor_id[DAKTARI_MAX_PS][DAK_MAX_PS_I_SENSORS]; 559 static char *power_supply_id[DAKTARI_MAX_PS] = {{NULL}}; 560 int32_t i, j; 561 int32_t amps, oc_flag = 0, ps_present = 0; 562 static int32_t hi_warn[DAKTARI_MAX_PS][DAK_MAX_PS_I_SENSORS]; 563 char state[32]; 564 static int8_t overcurrent_failed_check = 0; 565 static int8_t threshold_counter = 0; 566 567 if (power_supply_id[0] == NULL) { 568 for (i = 0; i < DAKTARI_MAX_PS; i++) { 569 status = psvc_get_attr(hdlp, system, 570 PSVC_ASSOC_ID_ATTR, &(power_supply_id[i]), 571 PSVC_PS, i); 572 if (status != PSVC_SUCCESS) 573 return (status); 574 for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) { 575 status = psvc_get_attr(hdlp, 576 power_supply_id[i], PSVC_ASSOC_ID_ATTR, 577 &(sensor_id[i][j]), PSVC_PS_I_SENSOR, j); 578 if (status != PSVC_SUCCESS) 579 return (status); 580 status = psvc_get_attr(hdlp, sensor_id[i][j], 581 PSVC_HI_WARN_ATTR, &(hi_warn[i][j])); 582 if (status != PSVC_SUCCESS) 583 return (status); 584 } 585 } 586 } 587 588 for (i = 0; i < DAKTARI_MAX_PS; i++) { 589 status = psvc_get_attr(hdlp, power_supply_id[i], 590 PSVC_PRESENCE_ATTR, &present); 591 if (status == PSVC_FAILURE) { 592 syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, 593 power_supply_id[i], errno); 594 return (status); 595 } 596 597 if (present == PSVC_ABSENT) { 598 continue; 599 } 600 601 status = psvc_check_ps_hotplug_status_0(hdlp, 602 power_supply_id[i]); 603 if (status == PSVC_FAILURE) 604 return (status); 605 606 status = psvc_get_attr(hdlp, power_supply_id[i], 607 PSVC_STATE_ATTR, state); 608 if (status == PSVC_FAILURE) 609 return (status); 610 611 if (strcmp(state, PSVC_HOTPLUGGED) == 0) { 612 continue; 613 } else { 614 ps_present++; 615 } 616 617 for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) { 618 status = psvc_get_attr(hdlp, sensor_id[i][j], 619 PSVC_SENSOR_VALUE_ATTR, &s); 620 if (status != PSVC_SUCCESS) { 621 if (overcurrent_failed_check == 0) { 622 /* 623 * First time the get_attr call 624 * failed set count so that if we 625 * fail again we will know 626 */ 627 overcurrent_failed_check = 1; 628 /* 629 * We probably failed because the power 630 * supply was just insterted or removed 631 * before the get_attr call. We then 632 * return from this policy successfully 633 * knowing it will be run again shortly 634 * with the right PS state. 635 */ 636 return (PSVC_SUCCESS); 637 } else { 638 /* 639 * We have failed before and so this we 640 * will consider a hardware problem and 641 * it should be reported. 642 */ 643 syslog(LOG_ERR, 644 "Failed getting %s sensor value", 645 sensor_id[i][j]); 646 return (status); 647 } 648 } 649 /* 650 * Because we have successfully gotten a value from the 651 * i2c device on the PS we will set the failed_count 652 * to 0. 653 */ 654 overcurrent_failed_check = 0; 655 656 if (amps >= hi_warn[i][j]) { 657 oc_flag = 1; 658 } 659 } 660 } 661 662 if (oc_flag) { 663 /* 664 * Because we observed an overcurrent 665 * condition, we increment threshold_counter. 666 * Once threshold_counter reaches the value 667 * of PSVC_THRESHOLD_COUNTER we log the event. 668 */ 669 threshold_counter++; 670 if (threshold_counter == PSVC_THRESHOLD_COUNTER) { 671 threshold_counter = 0; 672 if (ps_present == 1) { 673 syslog(LOG_ERR, PS_OVER_CURRENT_MSG); 674 syslog(LOG_ERR, ADD_PS_MSG); 675 } else { 676 syslog(LOG_ERR, PS_OVER_CURRENT_MSG); 677 syslog(LOG_ERR, REMOVE_LOAD_MSG); 678 } 679 } 680 } else { 681 threshold_counter = 0; 682 } 683 684 return (PSVC_SUCCESS); 685 } 686 687 int32_t 688 psvc_ps_device_fail_notifier_policy_0(psvc_opaque_t hdlp, char *system) 689 { 690 static char *ps_id[DAKTARI_MAX_PS] = {{NULL}}; 691 static char *sensor_id[DAKTARI_MAX_PS][DAK_MAX_FAULT_SENSORS]; 692 char *led_id = "FSP_POWER_FAULT_LED"; 693 int i, j; 694 char state[32], fault[32], previous_state[32], past_state[32]; 695 char led_state[32]; 696 char bad_sensors[DAK_MAX_FAULT_SENSORS][256]; 697 int32_t status = PSVC_SUCCESS; 698 boolean_t present; 699 int fail_state; 700 static int8_t device_fail_failed_check = 0; 701 int8_t retry, should_retry; 702 703 if (ps_id[0] == NULL) { 704 for (i = 0; i < DAKTARI_MAX_PS; i++) { 705 status = psvc_get_attr(hdlp, system, 706 PSVC_ASSOC_ID_ATTR, &(ps_id[i]), PSVC_PS, i); 707 if (status != PSVC_SUCCESS) 708 return (status); 709 for (j = 0; j < DAK_MAX_FAULT_SENSORS; j++) { 710 status = psvc_get_attr(hdlp, ps_id[i], 711 PSVC_ASSOC_ID_ATTR, &(sensor_id[i][j]), 712 PSVC_DEV_FAULT_SENSOR, j); 713 if (status != PSVC_SUCCESS) 714 return (status); 715 } 716 } 717 } 718 719 for (i = 0; i < DAKTARI_MAX_PS; i++) { 720 fail_state = 0; 721 status = psvc_get_attr(hdlp, ps_id[i], PSVC_PRESENCE_ATTR, 722 &present); 723 if (status == PSVC_FAILURE) 724 return (status); 725 726 if (present == PSVC_ABSENT) { 727 errno = ENODEV; 728 return (PSVC_FAILURE); 729 } 730 731 status = psvc_check_ps_hotplug_status_0(hdlp, ps_id[i]); 732 if (status == PSVC_FAILURE) 733 return (status); 734 735 status = psvc_get_attr(hdlp, ps_id[i], PSVC_STATE_ATTR, 736 past_state); 737 if (status == PSVC_FAILURE) 738 return (status); 739 740 if (strcmp(past_state, PSVC_HOTPLUGGED) == 0) { 741 return (PICL_SUCCESS); 742 } 743 744 retry = 0; 745 do { 746 if (retry) 747 sleep(1); 748 fail_state = 0; 749 should_retry = 0; 750 for (j = 0; j < DAK_MAX_FAULT_SENSORS; ++j) { 751 status = psvc_get_attr(hdlp, sensor_id[i][j], 752 PSVC_SWITCH_STATE_ATTR, state); 753 if (status != PSVC_SUCCESS) { 754 if (device_fail_failed_check == 0) { 755 /* 756 * First time the get_attr call 757 * failed set count so that 758 * if we fail again we will know 759 */ 760 device_fail_failed_check = 1; 761 /* 762 * We probably failed because 763 * the power supply was just 764 * insterted or removed before 765 * the get_attr call. We then 766 * return from this policy 767 * successfully knowing it will 768 * be run again shortly 769 * with the right PS state. 770 */ 771 return (PSVC_SUCCESS); 772 } else { 773 /* 774 * We have failed before and 775 * so this we will consider a 776 * hardware problem and 777 * it should be reported. 778 */ 779 syslog(LOG_ERR, "Failed in " 780 "getting sensor state for " 781 "%s\n", sensor_id[i][j]); 782 783 return (status); 784 } 785 } 786 787 /* 788 * Because we have successfully gotten 789 * a value from the i2c device on the 790 * PS we will set the failed_count to 0. 791 */ 792 device_fail_failed_check = 0; 793 794 /* 795 * If we find that the sensor is on we 796 * fill in the name of the sensor in 797 * the bad_sensor array. If the sensor 798 * is off we use EMPTY_STRING as a check 799 * later on as to when NOT to print out 800 * what is in bad_sensor[]. 801 */ 802 if (strcmp(state, PSVC_SWITCH_ON) == 0) { 803 fail_state++; 804 strlcpy(bad_sensors[j], sensor_id[i][j], 805 sizeof (bad_sensors[j])); 806 } else { 807 strcpy(bad_sensors[j], EMPTY_STRING); 808 } 809 } 810 retry++; 811 /* 812 * check to see if we need to retry. the conditions are: 813 * 814 * fail_state past_state retry 815 * -------------------------------------------------- 816 * + PSVC_OK yes 817 * 0 PSVC_ERROR yes 818 * + PSVC_ERROR no 819 * 0 PSVC_OK no 820 */ 821 if ((fail_state > 0) && 822 (strcmp(past_state, PSVC_OK) == 0)) { 823 should_retry = 1; 824 } else if ((fail_state == 0) && 825 (strcmp(past_state, PSVC_ERROR) == 0)) { 826 should_retry = 1; 827 } 828 } while ((retry < PSVC_NUM_OF_RETRIES) && should_retry); 829 830 if (fail_state != 0) { 831 strcpy(state, PSVC_ERROR); 832 strcpy(fault, PSVC_GEN_FAULT); 833 } else { 834 strcpy(state, PSVC_OK); 835 strcpy(fault, PSVC_NO_FAULT); 836 } 837 838 status = psvc_set_attr(hdlp, ps_id[i], PSVC_STATE_ATTR, state); 839 if (status != PSVC_SUCCESS) 840 return (status); 841 842 status = psvc_set_attr(hdlp, ps_id[i], PSVC_FAULTID_ATTR, 843 fault); 844 if (status != PSVC_SUCCESS) 845 return (status); 846 847 status = psvc_get_attr(hdlp, ps_id[i], PSVC_PREV_STATE_ATTR, 848 previous_state); 849 if (status != PSVC_SUCCESS) 850 return (status); 851 852 if (strcmp(state, previous_state) != 0) { 853 char dev_label[32]; 854 855 psvc_get_attr(hdlp, ps_id[i], PSVC_LABEL_ATTR, 856 dev_label); 857 858 if (strcmp(state, PSVC_ERROR) == 0) { 859 syslog(LOG_ERR, DEVICE_FAILURE_MSG, dev_label); 860 for (j = 0; j < DAK_MAX_FAULT_SENSORS; ++j) { 861 if (strcmp(bad_sensors[j], 862 EMPTY_STRING) != 0) 863 syslog(LOG_ERR, "%s\n", 864 bad_sensors[j]); 865 } 866 strcpy(led_state, PSVC_LED_ON); 867 } else { 868 syslog(LOG_ERR, DEVICE_OK_MSG, dev_label); 869 strcpy(led_state, PSVC_LED_OFF); 870 } 871 872 status = psvc_set_attr(hdlp, led_id, 873 PSVC_LED_STATE_ATTR, led_state); 874 if (status != PSVC_SUCCESS) { 875 syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, 876 errno); 877 return (status); 878 } 879 } 880 } 881 882 return (PSVC_SUCCESS); 883 } 884 885 int32_t 886 psvc_ps_check_and_disable_dr_policy_0(psvc_opaque_t hdlp, char *id) 887 { 888 char state[32]; 889 static char *name[DAKTARI_MAX_PS] = {{NULL}}; 890 int ps_cnt = 0; 891 int i, j; 892 int dr_conf; 893 int fd, rv; 894 boolean_t present; 895 char dev_path[sizeof (HPC3130_DEV)+8]; 896 unsigned char controller_names[HPC3130_CONTROLLERS] = 897 { 0xe2, 0xe6, 0xe8, 0xec }; 898 899 if (name[0] == NULL) { 900 for (i = 0; i < DAKTARI_MAX_PS; i++) { 901 rv = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 902 &(name[i]), PSVC_PS, i); 903 if (rv != PSVC_SUCCESS) 904 return (rv); 905 } 906 } 907 908 /* 909 * Go through the power supplies to make sure they're present 910 * and OK. 911 */ 912 ps_cnt = DAKTARI_MAX_PS; 913 for (i = 0; i < DAKTARI_MAX_PS; i++) { 914 rv = psvc_get_attr(hdlp, name[i], PSVC_PRESENCE_ATTR, 915 &present); 916 if (rv != PSVC_SUCCESS) 917 return (rv); 918 919 if (present != PSVC_PRESENT) { 920 ps_cnt--; 921 continue; 922 } else { 923 rv = psvc_get_attr(hdlp, name[i], PSVC_STATE_ATTR, 924 state); 925 if (rv != PSVC_SUCCESS) 926 return (rv); 927 928 if (strcmp(state, PSVC_OK)) 929 ps_cnt--; 930 } 931 } 932 933 /* 934 * No change in DR configuration is needed if the new power supply 935 * count equals the current count. 936 */ 937 if (ps_cnt == co_ps) 938 return (PSVC_SUCCESS); 939 940 /* 941 * Disable DR when hotplugged down to 1 power supply; enable DR when 942 * hotplugged up from 1 supply. 943 */ 944 assert(ps_cnt); 945 if ((co_ps == 0 || co_ps > 1) && ps_cnt != 1) { 946 co_ps = ps_cnt; 947 return (PSVC_SUCCESS); 948 } 949 dr_conf = (ps_cnt == 1 ? HPC3130_DR_DISABLE : HPC3130_DR_ENABLE); 950 co_ps = ps_cnt; 951 952 for (i = 0; i < HPC3130_CONTROLLERS; i++) { 953 for (j = 0; j < HPC3130_SLOTS; j++) { 954 (void) snprintf(dev_path, sizeof (dev_path), 955 HPC3130_DEV, controller_names[i], j); 956 fd = open(dev_path, O_RDWR); 957 if (fd == -1) 958 return (PSVC_FAILURE); 959 960 rv = ioctl(fd, HPC3130_CONF_DR, &dr_conf); 961 close(fd); 962 if (rv == -1) 963 return (PSVC_FAILURE); 964 } 965 } 966 967 return (PSVC_SUCCESS); 968 } 969 970 int32_t 971 psvc_fan_blast_shutoff_policy_0(psvc_opaque_t hdlp, char *id) 972 { 973 char switch_status[32]; 974 int32_t status = PSVC_SUCCESS; 975 976 status = psvc_get_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, switch_status); 977 if (status != PSVC_SUCCESS) 978 return (status); 979 status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, 980 PSVC_SWITCH_OFF); 981 if (status != PSVC_SUCCESS) 982 return (status); 983 status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, 984 PSVC_SWITCH_ON); 985 if (status != PSVC_SUCCESS) 986 return (status); 987 status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, 988 PSVC_SWITCH_OFF); 989 990 return (status); 991 } 992 993 int32_t 994 psvc_fan_fault_check_policy_0(psvc_opaque_t hdlp, char *system) 995 { 996 static char *fan_id[DAK_MAX_FANS] = {{NULL}}; 997 boolean_t enabled; 998 int32_t speed; 999 int32_t status = PSVC_SUCCESS; 1000 int r; 1001 static int8_t threshold_counter = 0; 1002 1003 if (fan_id[0] == NULL) { 1004 for (r = 0; r < DAK_MAX_FANS; r++) { 1005 status = psvc_get_attr(hdlp, system, 1006 PSVC_ASSOC_ID_ATTR, &(fan_id[r]), PSVC_FAN, r); 1007 if (status != PSVC_SUCCESS) 1008 return (status); 1009 } 1010 } 1011 1012 for (r = 0; r < DAK_MAX_FANS; r++) { 1013 status = psvc_get_attr(hdlp, fan_id[r], PSVC_ENABLE_ATTR, 1014 &enabled); 1015 if (status != PSVC_SUCCESS) 1016 return (status); 1017 1018 if (enabled == PSVC_ENABLED) { 1019 uint64_t features; 1020 char *switch_id; 1021 char switch_state[32], fan_state[32]; 1022 int fan_count, fans; 1023 char *other_fan_id; 1024 char fstate[32], ffault[32]; 1025 1026 /* 1027 * If any other fan on the fan tray has an ERROR state, 1028 * mark this fan bad and return 1029 */ 1030 psvc_get_attr(hdlp, fan_id[r], PSVC_ASSOC_MATCHES_ATTR, 1031 &fan_count, PSVC_FAN_TRAY_FANS); 1032 for (fans = 0; fans < fan_count; ++fans) { 1033 status = psvc_get_attr(hdlp, fan_id[r], 1034 PSVC_ASSOC_ID_ATTR, &other_fan_id, 1035 PSVC_FAN_TRAY_FANS, fans); 1036 if (status == PSVC_FAILURE) 1037 return (status); 1038 status = psvc_get_attr(hdlp, other_fan_id, 1039 PSVC_STATE_ATTR, fan_state); 1040 if (status != PSVC_SUCCESS) 1041 return (status); 1042 1043 if (strcmp(fan_state, PSVC_ERROR) == 0) { 1044 strlcpy(ffault, PSVC_GEN_FAULT, 1045 sizeof (ffault)); 1046 status = psvc_set_attr(hdlp, fan_id[r], 1047 PSVC_FAULTID_ATTR, ffault); 1048 if (status != PSVC_SUCCESS) 1049 return (status); 1050 1051 strlcpy(fstate, PSVC_ERROR, 1052 sizeof (fstate)); 1053 status = psvc_set_attr(hdlp, fan_id[r], 1054 PSVC_STATE_ATTR, fstate); 1055 1056 return (status); 1057 } 1058 } 1059 1060 /* 1061 * Select tachometer for IO or CPU primary/secondary 1062 * fans. 1063 */ 1064 pthread_mutex_lock(&fan_mutex); 1065 1066 status = psvc_get_attr(hdlp, fan_id[r], 1067 PSVC_ASSOC_ID_ATTR, &switch_id, 1068 PSVC_FAN_PRIM_SEC_SELECTOR, 0); 1069 1070 if (status != PSVC_FAILURE) { 1071 status = psvc_get_attr(hdlp, fan_id[r], 1072 PSVC_FEATURES_ATTR, &features); 1073 if (status == PSVC_FAILURE) { 1074 pthread_mutex_unlock(&fan_mutex); 1075 return (status); 1076 } 1077 1078 if (features & PSVC_DEV_PRIMARY) 1079 strlcpy(switch_state, PSVC_SWITCH_ON, 1080 sizeof (switch_state)); 1081 else 1082 strlcpy(switch_state, PSVC_SWITCH_OFF, 1083 sizeof (switch_state)); 1084 status = psvc_set_attr(hdlp, switch_id, 1085 PSVC_SWITCH_STATE_ATTR, switch_state); 1086 if (status == PSVC_FAILURE) { 1087 pthread_mutex_unlock(&fan_mutex); 1088 return (status); 1089 } 1090 1091 /* allow time for speed to be determined */ 1092 (void) poll(NULL, 0, 250); 1093 } 1094 1095 status = psvc_get_attr(hdlp, fan_id[r], 1096 PSVC_SENSOR_VALUE_ATTR, &speed); 1097 if (status != PSVC_SUCCESS) { 1098 pthread_mutex_unlock(&fan_mutex); 1099 return (status); 1100 } 1101 1102 pthread_mutex_unlock(&fan_mutex); 1103 1104 if (speed == 0) { 1105 threshold_counter++; 1106 if (threshold_counter == 1107 PSVC_THRESHOLD_COUNTER) { 1108 int32_t i; 1109 int32_t led_count; 1110 char led_state[32]; 1111 char *led_id; 1112 char *slot_id; 1113 char label[32]; 1114 char state[32], fault[32]; 1115 1116 threshold_counter = 0; 1117 strlcpy(fault, PSVC_GEN_FAULT, 1118 sizeof (fault)); 1119 status = psvc_set_attr(hdlp, fan_id[r], 1120 PSVC_FAULTID_ATTR, fault); 1121 if (status != PSVC_SUCCESS) 1122 return (status); 1123 1124 strlcpy(state, PSVC_ERROR, 1125 sizeof (state)); 1126 status = psvc_set_attr(hdlp, fan_id[r], 1127 PSVC_STATE_ATTR, state); 1128 if (status != PSVC_SUCCESS) 1129 return (status); 1130 1131 status = psvc_get_attr(hdlp, fan_id[r], 1132 PSVC_LABEL_ATTR, label); 1133 if (status != PSVC_SUCCESS) 1134 return (status); 1135 1136 syslog(LOG_ERR, DEVICE_FAILURE_MSG, 1137 label); 1138 1139 /* turn on fault LEDs */ 1140 psvc_get_attr(hdlp, fan_id[r], 1141 PSVC_ASSOC_MATCHES_ATTR, &led_count, 1142 PSVC_DEV_FAULT_LED); 1143 strlcpy(led_state, PSVC_LED_ON, 1144 sizeof (led_state)); 1145 for (i = 0; i < led_count; ++i) { 1146 status = psvc_get_attr(hdlp, 1147 fan_id[r], 1148 PSVC_ASSOC_ID_ATTR, &led_id, 1149 PSVC_DEV_FAULT_LED, i); 1150 if (status == PSVC_FAILURE) 1151 return (status); 1152 1153 status = psvc_set_attr(hdlp, 1154 led_id, PSVC_LED_STATE_ATTR, 1155 led_state); 1156 if (status == PSVC_FAILURE) 1157 return (status); 1158 } 1159 1160 /* turn on OK to remove LEDs */ 1161 1162 status = psvc_get_attr(hdlp, fan_id[r], 1163 PSVC_ASSOC_ID_ATTR, &slot_id, 1164 PSVC_PARENT, 0); 1165 if (status != PSVC_SUCCESS) 1166 return (status); 1167 1168 psvc_get_attr(hdlp, slot_id, 1169 PSVC_ASSOC_MATCHES_ATTR, &led_count, 1170 PSVC_SLOT_REMOVE_LED); 1171 strlcpy(led_state, PSVC_LED_ON, 1172 sizeof (led_state)); 1173 for (i = 0; i < led_count; ++i) { 1174 status = psvc_get_attr(hdlp, 1175 slot_id, 1176 PSVC_ASSOC_ID_ATTR, &led_id, 1177 PSVC_SLOT_REMOVE_LED, i); 1178 if (status == PSVC_FAILURE) 1179 return (status); 1180 1181 status = psvc_set_attr(hdlp, 1182 led_id, PSVC_LED_STATE_ATTR, 1183 led_state); 1184 if (status == PSVC_FAILURE) 1185 return (status); 1186 } 1187 } 1188 } 1189 } 1190 } 1191 1192 return (PSVC_SUCCESS); 1193 } 1194 1195 /* 1196 * This routine takes in the PSVC handle pointer, the PS name, and the 1197 * instance number (0, 1, or 2). It simply make a psvc_get call to get the 1198 * presence of each of the children under the PS. This call will set the 1199 * presence state of the child device if it was not there when the system 1200 * was booted. 1201 */ 1202 static int 1203 handle_ps_hotplug_children_presence(psvc_opaque_t hdlp, char *id) 1204 { 1205 char *sensor_id; 1206 char fail_valid_switch_id[PICL_PROPNAMELEN_MAX]; 1207 int32_t status = PSVC_SUCCESS; 1208 boolean_t presence; 1209 int j; 1210 1211 /* Get the Sensor Valid Switch presence */ 1212 snprintf(fail_valid_switch_id, sizeof (fail_valid_switch_id), "%s%s", 1213 id, "_SENSOR_VALID_SWITCH"); 1214 1215 status = psvc_get_attr(hdlp, fail_valid_switch_id, PSVC_PRESENCE_ATTR, 1216 &presence); 1217 if (status != PSVC_SUCCESS) 1218 return (status); 1219 1220 /* Go through each PS's fault sensors */ 1221 for (j = 0; j < DAK_MAX_FAULT_SENSORS; j++) { 1222 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1223 &(sensor_id), PSVC_DEV_FAULT_SENSOR, j); 1224 if (status != PSVC_SUCCESS) 1225 return (status); 1226 status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR, 1227 &presence); 1228 if (status != PSVC_SUCCESS) 1229 return (status); 1230 } 1231 1232 /* Go through each PS's current sensors */ 1233 for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) { 1234 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1235 &(sensor_id), PSVC_PS_I_SENSOR, j); 1236 if (status != PSVC_SUCCESS) 1237 return (status); 1238 status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR, 1239 &presence); 1240 if (status != PSVC_SUCCESS) 1241 return (status); 1242 1243 } 1244 1245 /* Go through each PS's onboard i2c hardware */ 1246 for (j = 0; j < 3; j++) { 1247 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1248 &(sensor_id), PSVC_PHYSICAL_DEVICE, j); 1249 if (status != PSVC_SUCCESS) 1250 return (status); 1251 status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR, 1252 &presence); 1253 if (status != PSVC_SUCCESS) 1254 return (status); 1255 } 1256 1257 return (status); 1258 } 1259 1260 static i2c_hp_t devices[3][3] = { 1261 {{{0, 0x90}, "adio", "i2c-pcf8591"}, {{0, 0x70}, "ioexp", "i2c-pcf8574"}, 1262 {{0, 0xa0}, "fru", "i2c-at24c64"}}, 1263 {{{0, 0x92}, "adio", "i2c-pcf8591"}, {{0, 0x72}, "ioexp", "i2c-pcf8574"}, 1264 {{0, 0xa2}, "fru", "i2c-at24c64"}}, 1265 {{{0, 0x94}, "adio", "i2c-pcf8591"}, {{0, 0x74}, "ioexp", "i2c-pcf8574"}, 1266 {{0, 0xa4}, "fru", "i2c-at24c64"}}, 1267 }; 1268 1269 int32_t 1270 psvc_ps_hotplug_policy_0(psvc_opaque_t hdlp, char *id) 1271 { 1272 boolean_t presence, previous_presence; 1273 int32_t status = PSVC_SUCCESS; 1274 char label[32], state[32], fault[32]; 1275 int32_t ps_instance, led_count; 1276 char *switch_id, *led_id; 1277 int i; 1278 picl_nodehdl_t parent_node; 1279 char parent_path[256], ps_path[256]; 1280 picl_nodehdl_t child_node; 1281 devctl_hdl_t bus_handle, dev_handle; 1282 devctl_ddef_t ddef_hdl; 1283 char pcf8574_devpath[256], pcf8591_devpath[256], fru_devpath[256]; 1284 int8_t retry; 1285 1286 status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, 1287 &previous_presence); 1288 if (status != PSVC_SUCCESS) 1289 return (status); 1290 1291 retry = 0; 1292 do { 1293 if (retry) 1294 sleep(1); 1295 1296 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 1297 if (status != PSVC_SUCCESS) 1298 return (status); 1299 retry++; 1300 } while ((retry < PSVC_NUM_OF_RETRIES) && 1301 (presence != previous_presence)); 1302 1303 if (presence == previous_presence) { 1304 /* No change */ 1305 return (status); 1306 } 1307 1308 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 1309 if (status != PSVC_SUCCESS) 1310 return (status); 1311 1312 /* convert name to node, and parent path */ 1313 psvcplugin_lookup(id, parent_path, &child_node); 1314 1315 if (presence == PSVC_PRESENT) { 1316 /* 1317 * Run this code if Power Supply was just added into the 1318 * System. This code toggles hotplug switch and adds the 1319 * PS and it's children to the picl tree. We then goto adding 1320 * device drivers at bottom of the routine. 1321 */ 1322 int32_t switch_count; 1323 char state[32], fault[32]; 1324 char switch_state[32]; 1325 1326 /* may detect presence before all connections are made */ 1327 (void) poll(NULL, 0, 500); 1328 1329 /* Device added */ 1330 syslog(LOG_ERR, DEVICE_INSERTED_MSG, label); 1331 1332 strcpy(state, PSVC_OK); 1333 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 1334 if (status != PSVC_SUCCESS) 1335 return (status); 1336 1337 strcpy(fault, PSVC_NO_FAULT); 1338 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 1339 if (status != PSVC_SUCCESS) 1340 return (status); 1341 1342 /* Enable i2c bus */ 1343 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 1344 &switch_count, PSVC_HOTPLUG_ENABLE_SWITCH); 1345 for (i = 0; i < switch_count; ++i) { 1346 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1347 &switch_id, PSVC_HOTPLUG_ENABLE_SWITCH, i); 1348 if (status == PSVC_FAILURE) 1349 return (status); 1350 1351 strcpy(switch_state, PSVC_SWITCH_OFF); 1352 status = psvc_set_attr(hdlp, switch_id, 1353 PSVC_SWITCH_STATE_ATTR, switch_state); 1354 if (status == PSVC_FAILURE) 1355 return (status); 1356 1357 strcpy(switch_state, PSVC_SWITCH_ON); 1358 status = psvc_set_attr(hdlp, switch_id, 1359 PSVC_SWITCH_STATE_ATTR, switch_state); 1360 if (status == PSVC_FAILURE) 1361 return (status); 1362 } 1363 ptree_get_node_by_path(parent_path, &parent_node); 1364 ptree_add_node(parent_node, child_node); 1365 snprintf(ps_path, sizeof (ps_path), "%s/%s", parent_path, id); 1366 psvcplugin_add_children(ps_path); 1367 } else { 1368 /* 1369 * Run this code if PS was just removed from the system. We 1370 * delete the device from the picl tree and then shut off 1371 * all fault lights associated with the PS. We also set the 1372 * device state to PSVC_REMOVED so that if we hit overcurrent 1373 * or fault checking code we can do a psvc call to see that 1374 * the device has not offically been added into the system. 1375 * We then will drop to code lower in the routine to remove 1376 * the device drivers for this PS. 1377 */ 1378 1379 /* Device removed */ 1380 syslog(LOG_ERR, DEVICE_REMOVED_MSG, label); 1381 ptree_delete_node(child_node); 1382 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &led_count, 1383 PSVC_DEV_FAULT_LED); 1384 1385 for (i = 0; i < led_count; i++) { 1386 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1387 &led_id, PSVC_DEV_FAULT_LED, i); 1388 if (status != PSVC_SUCCESS) { 1389 return (status); 1390 } 1391 1392 status = psvc_set_attr(hdlp, led_id, 1393 PSVC_LED_STATE_ATTR, PSVC_OFF); 1394 if (status != PSVC_SUCCESS) { 1395 syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, 1396 errno); 1397 return (status); 1398 } 1399 1400 } 1401 1402 strcpy(state, PSVC_OK); 1403 strcpy(fault, PSVC_NO_FAULT); 1404 1405 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 1406 if (status != PSVC_SUCCESS) 1407 return (status); 1408 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 1409 if (status != PSVC_SUCCESS) 1410 return (status); 1411 } 1412 1413 status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence); 1414 if (status != PSVC_SUCCESS) 1415 return (status); 1416 1417 status = psvc_get_attr(hdlp, id, PSVC_INSTANCE_ATTR, &ps_instance); 1418 if (status != PSVC_SUCCESS) 1419 return (status); 1420 1421 if (presence != PSVC_PRESENT) { 1422 /* 1423 * This is the additional code needed to remove the PS from 1424 * the system. It removes the device drivers from the 1425 * device tree. 1426 */ 1427 snprintf(pcf8574_devpath, sizeof (pcf8574_devpath), PCF8574, 1428 devices[ps_instance][1].addr[1]); 1429 snprintf(pcf8591_devpath, sizeof (pcf8591_devpath), PCF8591, 1430 devices[ps_instance][0].addr[1]); 1431 snprintf(fru_devpath, sizeof (fru_devpath), FRU, 1432 devices[ps_instance][2].addr[1]); 1433 1434 dev_handle = devctl_device_acquire(pcf8591_devpath, 0); 1435 if (dev_handle == NULL) { 1436 syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1437 pcf8591_devpath, errno); 1438 devctl_release(dev_handle); 1439 return (PSVC_FAILURE); 1440 } else if ((devctl_device_remove(dev_handle)) && 1441 (errno != ENXIO)) { 1442 syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, 1443 pcf8591_devpath, errno); 1444 devctl_release(dev_handle); 1445 return (PSVC_FAILURE); 1446 } else { 1447 devctl_release(dev_handle); 1448 status = PSVC_SUCCESS; 1449 } 1450 1451 dev_handle = devctl_device_acquire(pcf8574_devpath, 0); 1452 if (dev_handle == NULL) { 1453 syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1454 pcf8574_devpath, errno); 1455 devctl_release(dev_handle); 1456 return (PSVC_FAILURE); 1457 } else if ((devctl_device_remove(dev_handle)) && 1458 (errno != ENXIO)) { 1459 syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, 1460 pcf8574_devpath, errno); 1461 devctl_release(dev_handle); 1462 return (PSVC_FAILURE); 1463 } else { 1464 devctl_release(dev_handle); 1465 status = PSVC_SUCCESS; 1466 } 1467 1468 dev_handle = devctl_device_acquire(fru_devpath, 0); 1469 if (dev_handle == NULL) { 1470 syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1471 fru_devpath, errno); 1472 devctl_release(dev_handle); 1473 return (PSVC_FAILURE); 1474 } else if ((devctl_device_remove(dev_handle)) && 1475 (errno != ENXIO)) { 1476 syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, 1477 fru_devpath, errno); 1478 devctl_release(dev_handle); 1479 return (PSVC_FAILURE); 1480 } else { 1481 devctl_release(dev_handle); 1482 status = PSVC_SUCCESS; 1483 } 1484 1485 return (status); 1486 } 1487 1488 /* 1489 * This code is to update the presences of power supply child 1490 * devices in the event that picld was started without a power 1491 * supply present. This call makes the devices available 1492 * after that initial insertion. 1493 */ 1494 status = handle_ps_hotplug_children_presence(hdlp, id); 1495 if (status == PSVC_FAILURE) { 1496 return (status); 1497 } 1498 1499 /* 1500 * We fall through to here if the device has been inserted. 1501 * Add the devinfo tree node entry for the seeprom and attach 1502 * the i2c seeprom driver 1503 */ 1504 1505 bus_handle = devctl_bus_acquire(I2C_NODE, 0); 1506 if (bus_handle == NULL) { 1507 syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, I2C_NODE, errno); 1508 return (PSVC_FAILURE); 1509 } 1510 /* Create the deivce nodes for all 3 i2c parts on the PS */ 1511 for (i = 0; i < 3; i++) { 1512 ddef_hdl = devctl_ddef_alloc(devices[ps_instance][i].name, 0); 1513 if (ddef_hdl == NULL) { 1514 syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1515 devices[ps_instance][i].name, errno); 1516 return (PSVC_FAILURE); 1517 } 1518 status = devctl_ddef_string(ddef_hdl, "compatible", 1519 devices[ps_instance][i].compatible); 1520 if (status == -1) { 1521 syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1522 devices[ps_instance][i].name, errno); 1523 return (PSVC_FAILURE); 1524 } 1525 status = devctl_ddef_int_array(ddef_hdl, "reg", 2, 1526 devices[ps_instance][i].addr); 1527 if (status == -1) { 1528 syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1529 devices[ps_instance][i].name, errno); 1530 return (PSVC_FAILURE); 1531 } 1532 if (devctl_bus_dev_create(bus_handle, ddef_hdl, 0, 1533 &dev_handle)) { 1534 syslog(LOG_ERR, DEVTREE_NODE_CREATE_FAILED, 1535 devices[ps_instance][i].name, errno); 1536 return (PSVC_FAILURE); 1537 } else 1538 devctl_release(dev_handle); 1539 devctl_ddef_free(ddef_hdl); 1540 } 1541 devctl_release(bus_handle); 1542 1543 return (status); 1544 } 1545 1546 static void 1547 shutdown_routine() 1548 { 1549 static boolean_t shutdown_flag = 0; 1550 1551 if (!(shutdown_flag)) { 1552 system(shutdown_string); 1553 shutdown_flag = 1; 1554 } 1555 } 1556 1557 /* 1558 * This policy checks temperature sensors to see if the fault attribute 1559 * is set to either High or Low Shutdown. If so then it shuts the system 1560 * down with a 1 minute warning period 1561 */ 1562 int32_t 1563 psvc_shutdown_policy(psvc_opaque_t hdlp, char *id) 1564 { 1565 int32_t status; 1566 char fault[32] = {0}; 1567 boolean_t pr; 1568 1569 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &pr); 1570 if ((status != PSVC_SUCCESS) || (pr != PSVC_PRESENT)) { 1571 return (status); 1572 } 1573 1574 status = psvc_get_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 1575 if (status != PSVC_SUCCESS) 1576 return (status); 1577 1578 if ((strcmp(fault, PSVC_TEMP_LO_SHUT) == 0) || 1579 (strcmp(fault, PSVC_TEMP_HI_SHUT) == 0)) { 1580 shutdown_routine(); 1581 } 1582 1583 return (PSVC_SUCCESS); 1584 } 1585 1586 int32_t 1587 psvc_check_disk_fault_policy_0(psvc_opaque_t hdlp, char *id) 1588 { 1589 int32_t status = PSVC_SUCCESS; 1590 int32_t i; 1591 char curr_state[32], prev_state[32], led_state[32]; 1592 char disk_fault[32], disk_state[32]; 1593 static char *disk_id[DAK_MAX_DISKS] = {{NULL}}; 1594 static char *led_id[DAK_MAX_DISKS] = {{NULL}}; 1595 static char *parent_id[DAK_MAX_DISKS] = {{NULL}}; 1596 boolean_t present; 1597 int8_t retry; 1598 1599 /* 1600 * Check which disk faulted, now get the disks. 1601 * We are now going to get disk, disk parent, 1602 * parent's leds, and check to see if parent's leds are on 1603 */ 1604 1605 if (disk_id[0] == NULL) { 1606 for (i = 0; i < DAK_MAX_DISKS; i++) { 1607 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1608 &(disk_id[i]), PSVC_DISK, i); 1609 if (status != PSVC_SUCCESS) 1610 return (status); 1611 status = psvc_get_attr(hdlp, disk_id[i], 1612 PSVC_ASSOC_ID_ATTR, &(parent_id[i]), 1613 PSVC_PARENT, 0); 1614 if (status != PSVC_SUCCESS) 1615 return (status); 1616 status = psvc_get_attr(hdlp, parent_id[i], 1617 PSVC_ASSOC_ID_ATTR, &(led_id[i]), 1618 PSVC_SLOT_FAULT_LED, 0); 1619 if (status != PSVC_SUCCESS) 1620 return (status); 1621 1622 } 1623 } 1624 1625 for (i = 0; i < DAK_MAX_DISKS; i++) { 1626 curr_state[0] = 0; 1627 prev_state[0] = 0; 1628 1629 status = psvc_get_attr(hdlp, disk_id[i], PSVC_PRESENCE_ATTR, 1630 &present); 1631 if (status != PSVC_SUCCESS) 1632 return (status); 1633 1634 if (present == PSVC_ABSENT) 1635 continue; 1636 1637 /* 1638 * Check if whether or not the led is on. 1639 * If so, then this disk has a problem and 1640 * set its fault and error states to bad. 1641 * If not, then set fault and error states to good. 1642 * If the disk underwent a change in state, then 1643 * print out what state it's now in. 1644 */ 1645 1646 status = psvc_get_attr(hdlp, disk_id[i], PSVC_STATE_ATTR, 1647 prev_state); 1648 if (status != PSVC_SUCCESS) 1649 return (status); 1650 1651 retry = 0; 1652 do { 1653 if (retry) 1654 sleep(1); 1655 status = psvc_get_attr(hdlp, led_id[i], PSVC_STATE_ATTR, 1656 led_state); 1657 if (status != PSVC_SUCCESS) 1658 return (status); 1659 retry++; 1660 /* 1661 * check to see if we need to retry. the conditions are: 1662 * 1663 * prev_state led_state retry 1664 * -------------------------------------------------- 1665 * PSVC_ERROR PSVC_LED_ON yes 1666 * PSVC_OK PSVC_LED_OFF yes 1667 * PSVC_ERROR PSVC_LED_OFF no 1668 * PSVC_OK PSVC_LED_ON no 1669 */ 1670 } while ((retry < PSVC_NUM_OF_RETRIES) && 1671 change_of_state_str(prev_state, PSVC_OK, 1672 led_state, PSVC_LED_ON)); 1673 1674 /* 1675 * Set the disk's state and fault id according to 1676 * what we found the disk fault sensor (disk_slot_fault_led) 1677 * to be. 1678 */ 1679 if (strcmp(led_state, PSVC_LED_ON) == 0) { 1680 strcpy(disk_fault, PSVC_GEN_FAULT); 1681 strcpy(disk_state, PSVC_ERROR); 1682 } else { 1683 strcpy(disk_fault, PSVC_NO_FAULT); 1684 strcpy(disk_state, PSVC_OK); 1685 } 1686 status = psvc_set_attr(hdlp, disk_id[i], PSVC_STATE_ATTR, 1687 disk_state); 1688 if (status != PSVC_SUCCESS) 1689 return (status); 1690 status = psvc_set_attr(hdlp, disk_id[i], PSVC_FAULTID_ATTR, 1691 disk_fault); 1692 if (status != PSVC_SUCCESS) 1693 return (status); 1694 /* 1695 * Check disk states. If they differ, then print out 1696 * the current state of the disk 1697 */ 1698 status = psvc_get_attr(hdlp, disk_id[i], PSVC_PREV_STATE_ATTR, 1699 prev_state); 1700 if (status != PSVC_SUCCESS) 1701 return (status); 1702 1703 if (strcmp(disk_state, prev_state) != 0) { 1704 if (strcmp(disk_state, PSVC_ERROR) == 0) { 1705 syslog(LOG_ERR, DISK_FAULT_MSG, disk_id[i]); 1706 } else { 1707 syslog(LOG_ERR, DISK_OK_MSG, disk_id[i]); 1708 } 1709 } 1710 } 1711 return (PSVC_SUCCESS); 1712 } 1713 1714 int32_t 1715 psvc_update_FSP_fault_led_policy_0(psvc_opaque_t hdlp, char *id) 1716 { 1717 int32_t status = PSVC_SUCCESS; 1718 int32_t i; 1719 int32_t dev_count, fault_state = 0; 1720 char *dev_id; 1721 char dev_state[32], led_state[32]; 1722 boolean_t present; 1723 1724 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &dev_count, 1725 PSVC_DEV_FAULT_SENSOR); 1726 if (status != PSVC_SUCCESS) 1727 return (status); 1728 1729 fault_state = 0; 1730 1731 for (i = 0; i < dev_count; i++) { 1732 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1733 &dev_id, PSVC_DEV_FAULT_SENSOR, i); 1734 if (status != PSVC_SUCCESS) 1735 return (status); 1736 status = psvc_get_attr(hdlp, dev_id, PSVC_PRESENCE_ATTR, 1737 &present); 1738 if (status != PSVC_SUCCESS) 1739 return (status); 1740 1741 if (present == PSVC_ABSENT) 1742 continue; 1743 1744 status = psvc_get_attr(hdlp, dev_id, PSVC_STATE_ATTR, 1745 dev_state); 1746 if (status != PSVC_SUCCESS) 1747 return (status); 1748 1749 if (strcmp(dev_state, PSVC_ERROR) == 0) { 1750 fault_state = 1; 1751 } 1752 } 1753 if (fault_state == 1) { 1754 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 1755 if (status != PSVC_SUCCESS) 1756 return (status); 1757 if (strcmp(led_state, PSVC_OFF) == 0) { 1758 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 1759 PSVC_ON); 1760 if (status != PSVC_SUCCESS) 1761 return (status); 1762 } 1763 } else { 1764 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 1765 if (status != PSVC_SUCCESS) 1766 return (status); 1767 if (strcmp(led_state, PSVC_ON) == 0) { 1768 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 1769 PSVC_OFF); 1770 if (status != PSVC_SUCCESS) 1771 return (status); 1772 } 1773 } 1774 status = update_gen_fault_led(hdlp, GEN_FAULT_LED); 1775 1776 return (status); 1777 } 1778 1779 int32_t 1780 update_gen_fault_led(psvc_opaque_t hdlp, char *id) 1781 { 1782 int32_t status = PSVC_SUCCESS; 1783 int32_t i; 1784 int32_t led_count, fault_state; 1785 char *led_id; 1786 char led_state[32]; 1787 1788 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &led_count, 1789 PSVC_DEV_FAULT_SENSOR); 1790 if (status != PSVC_SUCCESS) 1791 return (status); 1792 1793 fault_state = 0; 1794 1795 for (i = 0; i < led_count; i++) { 1796 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1797 &led_id, PSVC_DEV_FAULT_SENSOR, i); 1798 if (status != PSVC_SUCCESS) 1799 return (status); 1800 status = psvc_get_attr(hdlp, led_id, PSVC_STATE_ATTR, 1801 led_state); 1802 if (status != PSVC_SUCCESS) 1803 return (status); 1804 1805 if (strcmp(led_state, PSVC_ON) == 0) { 1806 fault_state = 1; 1807 } 1808 } 1809 1810 if (fault_state == 1) { 1811 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 1812 if (status != PSVC_SUCCESS) 1813 return (status); 1814 if (strcmp(led_state, PSVC_OFF) == 0) { 1815 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 1816 PSVC_ON); 1817 if (status != PSVC_SUCCESS) 1818 return (status); 1819 } 1820 } else { 1821 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 1822 if (status != PSVC_SUCCESS) 1823 return (status); 1824 if (strcmp(led_state, PSVC_ON) == 0) { 1825 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 1826 PSVC_OFF); 1827 if (status != PSVC_SUCCESS) 1828 return (status); 1829 } 1830 } 1831 1832 return (status); 1833 } 1834 1835 1836 /* 1837 * This function detects whether the module present in the dakatari's 1838 * CPU slot is a CPU module or a Zulu (XVR-4000). 1839 * Based on this detection it also sets the appropriate temperature sensors 1840 * to HOTPLUGGED, so that it works properly with check_temp() function 1841 */ 1842 #define MAX_MODULE_SIZE 20 1843 #define MAX_TEMP_SENSOR_SIZE 30 1844 1845 int32_t 1846 psvc_update_cpu_module_card_node_0(psvc_opaque_t hdlp, char *id) 1847 { 1848 int32_t set_temp_sensor_properties(psvc_opaque_t, char *); 1849 int32_t remove_module_node(psvc_opaque_t, char *); 1850 int32_t status = PSVC_SUCCESS; 1851 fru_info_t fru_data; 1852 char *fru, seg_name[2]; 1853 int8_t seg_count, module_card; 1854 int32_t match_count, i, j, seg_desc_start = 0x1806, module_address; 1855 int32_t seg_found; 1856 boolean_t present; 1857 seg_desc_t segment; 1858 char other_module_id[MAX_MODULE_SIZE]; 1859 char cpu_temp_sensor1[MAX_TEMP_SENSOR_SIZE]; 1860 char cpu_temp_sensor2[MAX_TEMP_SENSOR_SIZE]; 1861 char zulu_temp_sensor1[MAX_TEMP_SENSOR_SIZE]; 1862 char zulu_temp_sensor2[MAX_TEMP_SENSOR_SIZE]; 1863 int offset = 0x7; 1864 1865 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 1866 if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) { 1867 return (status); 1868 } 1869 1870 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count, 1871 PSVC_FRU); 1872 if (status == PSVC_FAILURE) { 1873 return (status); 1874 } 1875 1876 for (i = 0; i < match_count; i++) { 1877 seg_found = 0; 1878 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &fru, 1879 PSVC_FRU, i); 1880 if (status != PSVC_SUCCESS) 1881 return (status); 1882 1883 fru_data.buf_start = 0x1805; 1884 fru_data.buf = (char *)&seg_count; 1885 fru_data.read_size = 1; 1886 1887 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 1888 &fru_data); 1889 if (status != PSVC_SUCCESS) { 1890 return (status); 1891 } 1892 1893 for (j = 0; (j < seg_count) && (!seg_found); j++) { 1894 fru_data.buf_start = seg_desc_start; 1895 fru_data.buf = seg_name; 1896 fru_data.read_size = 2; 1897 1898 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 1899 &fru_data); 1900 if (status != PSVC_SUCCESS) { 1901 syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG); 1902 return (status); 1903 } 1904 1905 seg_desc_start = seg_desc_start + 2; 1906 fru_data.buf_start = seg_desc_start; 1907 fru_data.buf = (char *)&segment; 1908 fru_data.read_size = sizeof (seg_desc_t); 1909 1910 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 1911 &fru_data); 1912 if (status != PSVC_SUCCESS) { 1913 syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG); 1914 return (status); 1915 } 1916 seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 1917 if (memcmp(seg_name, "SC", 2) == 0) 1918 seg_found = 1; 1919 } 1920 1921 if (seg_found) { 1922 module_address = segment.segoffset + offset; 1923 fru_data.buf_start = module_address; 1924 fru_data.buf = (char *)&module_card; 1925 fru_data.read_size = 1; 1926 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 1927 &fru_data); 1928 if (status != PSVC_SUCCESS) { 1929 syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG); 1930 return (status); 1931 } 1932 } else { 1933 syslog(LOG_ERR, NO_FRU_INFO_MSG, id); 1934 } 1935 } 1936 1937 if (strcmp(id, "ZULU_1_3_MOD_CARD") == 0) { 1938 strlcpy(other_module_id, "CPU_1_3_MOD_CARD", MAX_MODULE_SIZE); 1939 1940 strlcpy(cpu_temp_sensor1, "CPU1_DIE_TEMPERATURE_SENSOR", 1941 MAX_TEMP_SENSOR_SIZE); 1942 strlcpy(cpu_temp_sensor2, "CPU3_DIE_TEMPERATURE_SENSOR", 1943 MAX_TEMP_SENSOR_SIZE); 1944 1945 strlcpy(zulu_temp_sensor1, "ZULU1_DIE_TEMPERATURE_SENSOR", 1946 MAX_TEMP_SENSOR_SIZE); 1947 strlcpy(zulu_temp_sensor2, "ZULU3_DIE_TEMPERATURE_SENSOR", 1948 MAX_TEMP_SENSOR_SIZE); 1949 } 1950 1951 if (strcmp(id, "ZULU_4_6_MOD_CARD") == 0) { 1952 strlcpy(other_module_id, "CPU_4_6_MOD_CARD", MAX_MODULE_SIZE); 1953 1954 strlcpy(cpu_temp_sensor1, "CPU4_DIE_TEMPERATURE_SENSOR", 1955 MAX_TEMP_SENSOR_SIZE); 1956 strlcpy(cpu_temp_sensor2, "CPU6_DIE_TEMPERATURE_SENSOR", 1957 MAX_TEMP_SENSOR_SIZE); 1958 1959 strlcpy(zulu_temp_sensor1, "ZULU4_DIE_TEMPERATURE_SENSOR", 1960 MAX_TEMP_SENSOR_SIZE); 1961 strlcpy(zulu_temp_sensor2, "ZULU6_DIE_TEMPERATURE_SENSOR", 1962 MAX_TEMP_SENSOR_SIZE); 1963 } 1964 1965 1966 /* 1967 * If the module in the CPU slot is a Zulu (XVR-4000), then 1968 * location 0x1EB0 in its FRUid prom has a value 0xFB. 1969 * If Zulu (XVR-4000) is detected, delete the CPU node, otherwise 1970 * delete the Zulu node. Also set the temperature sensor value to 1971 * HOTPLUGGED for absent temperature sensors. 1972 */ 1973 if ((module_card & 0xff) == 0xfb) { 1974 status = set_temp_sensor_properties(hdlp, cpu_temp_sensor1); 1975 if (status == PSVC_FAILURE) { 1976 return (status); 1977 } 1978 1979 status = set_temp_sensor_properties(hdlp, cpu_temp_sensor2); 1980 if (status == PSVC_FAILURE) { 1981 return (status); 1982 } 1983 1984 /* 1985 * Remove CPU node 1986 */ 1987 status = remove_module_node(hdlp, other_module_id); 1988 if (status == PSVC_FAILURE) { 1989 return (status); 1990 } 1991 } else { 1992 status = set_temp_sensor_properties(hdlp, zulu_temp_sensor1); 1993 if (status == PSVC_FAILURE) { 1994 return (status); 1995 } 1996 status = set_temp_sensor_properties(hdlp, zulu_temp_sensor2); 1997 if (status == PSVC_FAILURE) { 1998 return (status); 1999 } 2000 2001 /* 2002 * Remove Zulu (XVR-4000) node 2003 */ 2004 status = remove_module_node(hdlp, id); 2005 if (status == PSVC_FAILURE) { 2006 return (status); 2007 } 2008 } 2009 2010 return (PSVC_SUCCESS); 2011 } 2012 2013 2014 /* 2015 * Remove the CPU slot's module node 2016 */ 2017 int32_t 2018 remove_module_node(psvc_opaque_t hdlp, char *id) 2019 { 2020 char parent_path[256]; 2021 picl_nodehdl_t child_node; 2022 2023 /* convert name to node, and parent path */ 2024 psvcplugin_lookup(id, parent_path, &child_node); 2025 /* Device removed */ 2026 ptree_delete_node(child_node); 2027 2028 return (PSVC_SUCCESS); 2029 } 2030 2031 2032 /* 2033 * Set absent temperature sensor values to HOTPLUGGED 2034 */ 2035 int32_t 2036 set_temp_sensor_properties(psvc_opaque_t hdlp, char *id) 2037 { 2038 char state[32]; 2039 int32_t status = PSVC_SUCCESS; 2040 2041 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state); 2042 if (status == PSVC_FAILURE) { 2043 return (status); 2044 } 2045 2046 if (strcmp(state, PSVC_HOTPLUGGED) != 0) { 2047 strcpy(state, PSVC_HOTPLUGGED); 2048 2049 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 2050 if (status == PSVC_FAILURE) { 2051 return (status); 2052 } 2053 } 2054 2055 return (PSVC_SUCCESS); 2056 } 2057