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