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