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