17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*5eb92cf2Sdhain * Common Development and Distribution License (the "License"). 6*5eb92cf2Sdhain * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*5eb92cf2Sdhain * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * Daktari platform platform specific environment monitoring policies 307c478bd9Sstevel@tonic-gate */ 317c478bd9Sstevel@tonic-gate #include <poll.h> 327c478bd9Sstevel@tonic-gate #include <syslog.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <errno.h> 377c478bd9Sstevel@tonic-gate #include <fcntl.h> 387c478bd9Sstevel@tonic-gate #include <strings.h> 397c478bd9Sstevel@tonic-gate #include <libintl.h> 407c478bd9Sstevel@tonic-gate #include <sys/types.h> 417c478bd9Sstevel@tonic-gate #include <sys/param.h> 427c478bd9Sstevel@tonic-gate #include <config_admin.h> 437c478bd9Sstevel@tonic-gate #include <libdevice.h> 447c478bd9Sstevel@tonic-gate #include <picl.h> 457c478bd9Sstevel@tonic-gate #include <picltree.h> 467c478bd9Sstevel@tonic-gate #include <psvc_objects.h> 477c478bd9Sstevel@tonic-gate #include <sys/i2c/clients/i2c_client.h> 487c478bd9Sstevel@tonic-gate #include <sys/daktari.h> 497c478bd9Sstevel@tonic-gate #include <sys/hpc3130_events.h> 507c478bd9Sstevel@tonic-gate #include <assert.h> 51298b7f4cSjfrank #include <limits.h> 52298b7f4cSjfrank #include <sys/systeminfo.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate /* resides in libcfgadm */ 577c478bd9Sstevel@tonic-gate extern cfga_err_t config_change_state(cfga_cmd_t, int, char *const *, 587c478bd9Sstevel@tonic-gate const char *, struct cfga_confirm *, struct cfga_msg *, char **, 597c478bd9Sstevel@tonic-gate cfga_flags_t); 607c478bd9Sstevel@tonic-gate /* Local Routine */ 617c478bd9Sstevel@tonic-gate static int32_t update_gen_fault_led(psvc_opaque_t, char *); 627c478bd9Sstevel@tonic-gate static void shutdown_routine(void); 637c478bd9Sstevel@tonic-gate static int32_t update_thresholds(psvc_opaque_t hdlp, char *id, int offset); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate #ifdef DEBUG 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate static int dak_policy_debug = 0; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate #define D1SYS_ERR(ARGS) if (dak_policy_debug & 0x1) syslog ARGS; 717c478bd9Sstevel@tonic-gate #define D2SYS_ERR(ARGS) if (dak_policy_debug & 0x2) syslog ARGS; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate #else 747c478bd9Sstevel@tonic-gate 757c478bd9Sstevel@tonic-gate #define D1SYS_ERR(ARGS) 767c478bd9Sstevel@tonic-gate #define D2SYS_ERR(ARGS) 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate #endif 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate #define I2C_PATH "/devices/pci@9,700000/ebus@1/i2c@1,30" 81159cf8a6Swesolows #define I2C_NODE I2C_PATH ":devctl" 82159cf8a6Swesolows #define PCF8574 I2C_PATH "/ioexp@0,%x:pcf8574" 83159cf8a6Swesolows #define PCF8591 I2C_PATH "/adio@0,%x:port_0" 84159cf8a6Swesolows #define FRU I2C_PATH "/fru@0,%x:fru" 85159cf8a6Swesolows #define HPC3130_DEV I2C_PATH "/hotplug-controller@0,%2x:port_%1x" 867c478bd9Sstevel@tonic-gate #define GEN_FAULT_LED "FSP_GEN_FAULT_LED" 877c478bd9Sstevel@tonic-gate #define EMPTY_STRING "EMPTY" 887c478bd9Sstevel@tonic-gate #define DEVICE_FAILURE_MSG gettext("WARNING: Device %s failure detected") 897c478bd9Sstevel@tonic-gate #define DEVICE_INSERTED_MSG gettext("Device %s inserted") 907c478bd9Sstevel@tonic-gate #define DEVICE_REMOVED_MSG gettext("Device %s removed") 917c478bd9Sstevel@tonic-gate #define PS_UNPLUGGED_MSG gettext("Device %s unplugged") 927c478bd9Sstevel@tonic-gate #define PS_PLUGGED_MSG gettext("Device %s Plugged in") 937c478bd9Sstevel@tonic-gate #define DEVICE_OK_MSG gettext("Device %s OK") 947c478bd9Sstevel@tonic-gate #define SET_LED_FAILED_MSG \ 957c478bd9Sstevel@tonic-gate gettext("Failed to set LED state, id = %s, errno = %d\n") 967c478bd9Sstevel@tonic-gate #define GET_PRESENCE_FAILED_MSG \ 977c478bd9Sstevel@tonic-gate gettext("Failed to get presence attribute, id = %s, errno = %d\n") 987c478bd9Sstevel@tonic-gate #define GET_SENSOR_FAILED_MSG \ 997c478bd9Sstevel@tonic-gate gettext("Failed to get sensor value, id = %s, errno = %d\n") 1007c478bd9Sstevel@tonic-gate #define ADD_PS_MSG \ 1017c478bd9Sstevel@tonic-gate gettext("WARNING: Only 1 Power Supply in system. ADD a 2nd Power Supply.\n") 1027c478bd9Sstevel@tonic-gate #define REMOVE_LOAD_MSG \ 1037c478bd9Sstevel@tonic-gate gettext("WARNING: Power Supply at 95%% current. Remove some load.\n") 1047c478bd9Sstevel@tonic-gate #define PS_OVER_CURRENT_MSG \ 1057c478bd9Sstevel@tonic-gate gettext("WARNING: Power Supply overcurrent detected\n") 1067c478bd9Sstevel@tonic-gate #define DEVICE_UNKNOWN_MSG gettext("Unknown device %s instance %d\n") 1077c478bd9Sstevel@tonic-gate #define DEVICE_HANDLE_FAIL_MSG \ 1087c478bd9Sstevel@tonic-gate gettext("Failed to get device handle for %s, errno = %d\n") 1097c478bd9Sstevel@tonic-gate #define DEVTREE_NODE_CREATE_FAILED \ 1107c478bd9Sstevel@tonic-gate gettext("psvc PICL plugin: Failed to create node for %s, errno = %d") 1117c478bd9Sstevel@tonic-gate #define DEVTREE_NODE_DELETE_FAILED \ 1127c478bd9Sstevel@tonic-gate gettext("psvc PICL plugin: Failed to delete node for %s, errno = %d") 1137c478bd9Sstevel@tonic-gate #define DISK_FAULT_MSG gettext("%s: Error Reported\n") 1147c478bd9Sstevel@tonic-gate #define DISK_OK_MSG gettext("%s: Error Cleared\n") 1157c478bd9Sstevel@tonic-gate #define SET_FANSPEED_FAILED_MSG \ 1167c478bd9Sstevel@tonic-gate gettext("Failed to set fan speed, id = %s, errno = %d\n") 1177c478bd9Sstevel@tonic-gate #define GET_ATTR_FRU_FAILED_MSG gettext("Failed psvc_get_attr for FRU info\n") 1187c478bd9Sstevel@tonic-gate #define NO_FRU_INFO_MSG \ 1197c478bd9Sstevel@tonic-gate gettext("No FRU Information for %s using default module card\n") 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate #define DAKTARI_MAX_PS 3 1227c478bd9Sstevel@tonic-gate #define DAK_MAX_PS_I_SENSORS 4 1237c478bd9Sstevel@tonic-gate #define DAK_MAX_DISKS 12 1247c478bd9Sstevel@tonic-gate #define DAK_MAX_CPU_MOD 4 1257c478bd9Sstevel@tonic-gate #define DAK_MAX_FAULT_SENSORS 3 1267c478bd9Sstevel@tonic-gate #define DAK_MAX_FANS 10 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate static int co_ps = 0; 1297c478bd9Sstevel@tonic-gate static char *shutdown_string = "shutdown -y -g 60 -i 5 \"OVERTEMP condition\""; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate typedef struct i2c_hp { 1327c478bd9Sstevel@tonic-gate int32_t addr[2]; 1337c478bd9Sstevel@tonic-gate char name[256]; 1347c478bd9Sstevel@tonic-gate char compatible[256]; 1357c478bd9Sstevel@tonic-gate } i2c_hp_t; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate typedef struct seg_desc { 1387c478bd9Sstevel@tonic-gate int32_t segdesc; 1397c478bd9Sstevel@tonic-gate int16_t segoffset; 1407c478bd9Sstevel@tonic-gate int16_t seglength; 1417c478bd9Sstevel@tonic-gate } seg_desc_t; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate static int32_t threshold_names[] = { 1447c478bd9Sstevel@tonic-gate PSVC_HW_LO_SHUT_ATTR, 1457c478bd9Sstevel@tonic-gate PSVC_LO_SHUT_ATTR, 1467c478bd9Sstevel@tonic-gate PSVC_LO_WARN_ATTR, 1477c478bd9Sstevel@tonic-gate PSVC_NOT_USED, /* LOW MODE which is not used */ 1487c478bd9Sstevel@tonic-gate PSVC_OPTIMAL_TEMP_ATTR, 1497c478bd9Sstevel@tonic-gate PSVC_HI_WARN_ATTR, 1507c478bd9Sstevel@tonic-gate PSVC_HI_SHUT_ATTR, 1517c478bd9Sstevel@tonic-gate PSVC_HW_HI_SHUT_ATTR 1527c478bd9Sstevel@tonic-gate }; 1537c478bd9Sstevel@tonic-gate 154298b7f4cSjfrank /* 155298b7f4cSjfrank * The I2C bus is noisy, and the state may be incorrectly reported as 156298b7f4cSjfrank * having changed. When the state changes, we attempt to confirm by 157298b7f4cSjfrank * retrying. If any retries indicate that the state has not changed, we 158298b7f4cSjfrank * assume the state change(s) were incorrect and the state has not changed. 159298b7f4cSjfrank * The following variables are used to store the tuneable values read in 160298b7f4cSjfrank * from the optional i2cparam.conf file for this shared object library. 161298b7f4cSjfrank */ 162298b7f4cSjfrank static int n_retry_pshp_status = PSVC_NUM_OF_RETRIES; 163298b7f4cSjfrank static int retry_sleep_pshp_status = 1; 164298b7f4cSjfrank static int n_read_overcurrent = PSVC_THRESHOLD_COUNTER; 165298b7f4cSjfrank static int n_retry_devicefail = PSVC_NUM_OF_RETRIES; 166298b7f4cSjfrank static int retry_sleep_devicefail = 1; 167298b7f4cSjfrank static int n_read_fanfault = PSVC_THRESHOLD_COUNTER; 168298b7f4cSjfrank static int n_retry_pshp = PSVC_NUM_OF_RETRIES; 169298b7f4cSjfrank static int retry_sleep_pshp = 1; 170298b7f4cSjfrank static int n_retry_diskfault = PSVC_NUM_OF_RETRIES; 171298b7f4cSjfrank static int retry_sleep_diskfault = 1; 172298b7f4cSjfrank static int n_retry_temp_shutdown = PSVC_NUM_OF_RETRIES; 173298b7f4cSjfrank static int retry_sleep_temp_shutdown = 1; 174298b7f4cSjfrank 175298b7f4cSjfrank typedef struct { 176298b7f4cSjfrank int *pvar; 177298b7f4cSjfrank char *texttag; 178298b7f4cSjfrank } i2c_noise_param_t; 179298b7f4cSjfrank 180298b7f4cSjfrank static i2c_noise_param_t i2cparams[] = { 181298b7f4cSjfrank &n_retry_pshp_status, "n_retry_pshp_status", 182298b7f4cSjfrank &retry_sleep_pshp_status, "retry_sleep_pshp_status", 183298b7f4cSjfrank &n_read_overcurrent, "n_read_overcurrent", 184298b7f4cSjfrank &n_retry_devicefail, "n_retry_devicefail", 185298b7f4cSjfrank &retry_sleep_devicefail, "retry_sleep_devicefail", 186298b7f4cSjfrank &n_read_fanfault, "n_read_fanfault", 187298b7f4cSjfrank &n_retry_pshp, "n_retry_pshp", 188298b7f4cSjfrank &retry_sleep_pshp, "retry_sleep_pshp", 189298b7f4cSjfrank &n_retry_diskfault, "n_retry_diskfault", 190298b7f4cSjfrank &retry_sleep_diskfault, "retry_sleep_diskfault", 191298b7f4cSjfrank &n_retry_temp_shutdown, "n_retry_temp_shutdown", 192298b7f4cSjfrank &retry_sleep_temp_shutdown, "retry_sleep_temp_shutdown", 193298b7f4cSjfrank NULL, NULL 194298b7f4cSjfrank }; 195298b7f4cSjfrank 196298b7f4cSjfrank #pragma init(i2cparams_load) 197298b7f4cSjfrank 198298b7f4cSjfrank static void 199298b7f4cSjfrank i2cparams_debug(i2c_noise_param_t *pi2cparams, char *platform, 200298b7f4cSjfrank int usingDefaults) 201298b7f4cSjfrank { 202298b7f4cSjfrank char s[128]; 203298b7f4cSjfrank i2c_noise_param_t *p; 204298b7f4cSjfrank 205298b7f4cSjfrank if (!usingDefaults) { 206298b7f4cSjfrank (void) snprintf(s, sizeof (s), 207298b7f4cSjfrank "# Values from /usr/platform/%s/lib/i2cparam.conf\n", 208298b7f4cSjfrank platform); 209298b7f4cSjfrank syslog(LOG_WARNING, "%s", s); 210298b7f4cSjfrank } else { 211298b7f4cSjfrank /* no file - we're using the defaults */ 212298b7f4cSjfrank (void) snprintf(s, sizeof (s), 213298b7f4cSjfrank "# No /usr/platform/%s/lib/i2cparam.conf file, using defaults\n", 214298b7f4cSjfrank platform); 215298b7f4cSjfrank } 216298b7f4cSjfrank (void) fputs(s, stdout); 217298b7f4cSjfrank p = pi2cparams; 218298b7f4cSjfrank while (p->pvar != NULL) { 219298b7f4cSjfrank (void) snprintf(s, sizeof (s), "%s %d\n", p->texttag, 220298b7f4cSjfrank *(p->pvar)); 221298b7f4cSjfrank if (!usingDefaults) 222298b7f4cSjfrank syslog(LOG_WARNING, "%s", s); 223298b7f4cSjfrank (void) fputs(s, stdout); 224298b7f4cSjfrank p++; 225298b7f4cSjfrank } 226298b7f4cSjfrank } 227298b7f4cSjfrank 228298b7f4cSjfrank static void 229298b7f4cSjfrank i2cparams_load(void) 230298b7f4cSjfrank { 231298b7f4cSjfrank FILE *fp; 232298b7f4cSjfrank char filename[PATH_MAX]; 233298b7f4cSjfrank char platform[64]; 234298b7f4cSjfrank char s[128]; 235298b7f4cSjfrank char var[128]; 236298b7f4cSjfrank int val; 237298b7f4cSjfrank i2c_noise_param_t *p; 238298b7f4cSjfrank 239298b7f4cSjfrank if (sysinfo(SI_PLATFORM, platform, sizeof (platform)) == -1) { 240298b7f4cSjfrank syslog(LOG_ERR, "sysinfo error %s\n", strerror(errno)); 241298b7f4cSjfrank return; 242298b7f4cSjfrank } 243298b7f4cSjfrank (void) snprintf(filename, sizeof (filename), 244298b7f4cSjfrank "/usr/platform/%s/lib/i2cparam.conf", platform); 245298b7f4cSjfrank /* read thru the i2cparam.conf file and set variables */ 246298b7f4cSjfrank if ((fp = fopen(filename, "r")) != NULL) { 247298b7f4cSjfrank while (fgets(s, sizeof (s), fp) != NULL) { 248298b7f4cSjfrank if (s[0] == '#') /* skip comment lines */ 249298b7f4cSjfrank continue; 250298b7f4cSjfrank /* try to find a string match and get the value */ 251298b7f4cSjfrank if (sscanf(s, "%127s %d", var, &val) != 2) 252298b7f4cSjfrank continue; 253298b7f4cSjfrank if (val < 1) 254298b7f4cSjfrank val = 1; /* clamp min value */ 255298b7f4cSjfrank p = &(i2cparams[0]); 256298b7f4cSjfrank while (p->pvar != NULL) { 257298b7f4cSjfrank if (strncmp(p->texttag, var, sizeof (var)) == 258298b7f4cSjfrank 0) { 259298b7f4cSjfrank *(p->pvar) = val; 260298b7f4cSjfrank break; 261298b7f4cSjfrank } 262298b7f4cSjfrank p++; 263298b7f4cSjfrank } 264298b7f4cSjfrank } 265298b7f4cSjfrank (void) fclose(fp); 266298b7f4cSjfrank } 267298b7f4cSjfrank /* output the values of the parameters */ 268298b7f4cSjfrank i2cparams_debug(&(i2cparams[0]), platform, ((fp == NULL)? 1 : 0)); 269298b7f4cSjfrank } 270298b7f4cSjfrank 2717c478bd9Sstevel@tonic-gate int32_t 2727c478bd9Sstevel@tonic-gate psvc_MB_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset) 2737c478bd9Sstevel@tonic-gate { 2747c478bd9Sstevel@tonic-gate int IO_offset = 0xd; 2757c478bd9Sstevel@tonic-gate int32_t err; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate err = update_thresholds(hdlp, id, IO_offset); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate return (err); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate int32_t 2837c478bd9Sstevel@tonic-gate psvc_IO_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset) 2847c478bd9Sstevel@tonic-gate { 2857c478bd9Sstevel@tonic-gate int IO_offset = 0x8; 2867c478bd9Sstevel@tonic-gate int32_t err; 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate err = update_thresholds(hdlp, id, IO_offset); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate return (err); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate int32_t 2947c478bd9Sstevel@tonic-gate psvc_DBP_update_thresholds_0(psvc_opaque_t hdlp, char *id, int offset) 2957c478bd9Sstevel@tonic-gate { 2967c478bd9Sstevel@tonic-gate int IO_offset = 0x7; 2977c478bd9Sstevel@tonic-gate int32_t err; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate err = update_thresholds(hdlp, id, IO_offset); 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate return (err); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* 3057c478bd9Sstevel@tonic-gate * used to determine if a change of state occured. valid when states 3067c478bd9Sstevel@tonic-gate * are strings. 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate static int8_t 3097c478bd9Sstevel@tonic-gate change_of_state_str(char *state1, char *check1, char *state2, char *check2) 3107c478bd9Sstevel@tonic-gate { 3117c478bd9Sstevel@tonic-gate int change = 0; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate if ((strcmp(state1, check1) == 0) && (strcmp(state2, check2) != 0)) 3147c478bd9Sstevel@tonic-gate change = 1; 3157c478bd9Sstevel@tonic-gate if ((strcmp(state1, check1) != 0) && (strcmp(state2, check2) == 0)) 3167c478bd9Sstevel@tonic-gate change = 1; 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate return (change); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 3227c478bd9Sstevel@tonic-gate * Update thresholds tries to read the temperature thresholds from the FRU 3237c478bd9Sstevel@tonic-gate * SEEproms and then updates the thresholds in the object by overriding the 3247c478bd9Sstevel@tonic-gate * hardcoded thresholds. For Daktari it is an Error if the FRU does not 3257c478bd9Sstevel@tonic-gate * contain the segment that had the temperature thresholds. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate static int32_t 3287c478bd9Sstevel@tonic-gate update_thresholds(psvc_opaque_t hdlp, char *id, int offset) 3297c478bd9Sstevel@tonic-gate { 3307c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 3317c478bd9Sstevel@tonic-gate fru_info_t fru_data; 3327c478bd9Sstevel@tonic-gate char *fru, seg_name[2]; 3337c478bd9Sstevel@tonic-gate int8_t seg_count, temp_array[8]; 3347c478bd9Sstevel@tonic-gate int32_t match_count, i, j, seg_desc_start = 0x1806, temp_address; 3357c478bd9Sstevel@tonic-gate int32_t seg_found, temp; 3367c478bd9Sstevel@tonic-gate boolean_t present; 3377c478bd9Sstevel@tonic-gate seg_desc_t segment; 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 3407c478bd9Sstevel@tonic-gate if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) 3417c478bd9Sstevel@tonic-gate return (status); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count, 3447c478bd9Sstevel@tonic-gate PSVC_FRU); 3457c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 3467c478bd9Sstevel@tonic-gate return (status); 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate for (i = 0; i < match_count; i++) { 3497c478bd9Sstevel@tonic-gate seg_found = 0; 3507c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 3517c478bd9Sstevel@tonic-gate &fru, PSVC_FRU, i); 3527c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 3537c478bd9Sstevel@tonic-gate return (status); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate fru_data.buf_start = 0x1805; 3567c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&seg_count; 3577c478bd9Sstevel@tonic-gate fru_data.read_size = 1; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 3607c478bd9Sstevel@tonic-gate &fru_data); 3617c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 3627c478bd9Sstevel@tonic-gate return (status); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate for (j = 0; (j < seg_count) && (!seg_found); j++) { 3657c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 3667c478bd9Sstevel@tonic-gate fru_data.buf = seg_name; 3677c478bd9Sstevel@tonic-gate fru_data.read_size = 2; 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 3707c478bd9Sstevel@tonic-gate &fru_data); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + 2; 3737c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 3747c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&segment; 3757c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (seg_desc_t); 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 3787c478bd9Sstevel@tonic-gate &fru_data); 3797c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 3807c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3817c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 3827c478bd9Sstevel@tonic-gate return (status); 3837c478bd9Sstevel@tonic-gate } 3847c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 3857c478bd9Sstevel@tonic-gate if (memcmp(seg_name, "SC", 2) == 0) 3867c478bd9Sstevel@tonic-gate seg_found = 1; 3877c478bd9Sstevel@tonic-gate } 3887c478bd9Sstevel@tonic-gate if (seg_found) { 3897c478bd9Sstevel@tonic-gate temp_address = segment.segoffset + offset; 3907c478bd9Sstevel@tonic-gate fru_data.buf_start = temp_address; 3917c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&temp_array; 3927c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (temp_array); 3937c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 3947c478bd9Sstevel@tonic-gate &fru_data); 3957c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 3967c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3977c478bd9Sstevel@tonic-gate "Failed psvc_get_attr for FRU info\n"); 3987c478bd9Sstevel@tonic-gate return (status); 3997c478bd9Sstevel@tonic-gate } else { 4007c478bd9Sstevel@tonic-gate for (j = 0; j < sizeof (temp_array); j++) { 4017c478bd9Sstevel@tonic-gate if (threshold_names[j] == 4027c478bd9Sstevel@tonic-gate PSVC_NOT_USED) 4037c478bd9Sstevel@tonic-gate continue; 4047c478bd9Sstevel@tonic-gate temp = temp_array[j]; 4057c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, 4067c478bd9Sstevel@tonic-gate threshold_names[j], &temp); 4077c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 4087c478bd9Sstevel@tonic-gate return (status); 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate } 4127c478bd9Sstevel@tonic-gate } else { 4137c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "No FRU Information for %s" 4147c478bd9Sstevel@tonic-gate " using default temperatures\n", id); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate return (status); 4187c478bd9Sstevel@tonic-gate } 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate int32_t 4217c478bd9Sstevel@tonic-gate psvc_fan_init_speed_0(psvc_opaque_t hdlp, char *id) 4227c478bd9Sstevel@tonic-gate { 4237c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 4247c478bd9Sstevel@tonic-gate boolean_t present; 4257c478bd9Sstevel@tonic-gate char *control_id; 4267c478bd9Sstevel@tonic-gate int32_t init_speed = 0; 4277c478bd9Sstevel@tonic-gate 4287c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 4297c478bd9Sstevel@tonic-gate if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) 4307c478bd9Sstevel@tonic-gate return (status); 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &control_id, 433*5eb92cf2Sdhain PSVC_FAN_DRIVE_CONTROL, 0); 4347c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4357c478bd9Sstevel@tonic-gate return (status); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, control_id, PSVC_CONTROL_VALUE_ATTR, 4387c478bd9Sstevel@tonic-gate &init_speed); 4397c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 4407c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SET_FANSPEED_FAILED_MSG, control_id, errno); 4417c478bd9Sstevel@tonic-gate return (status); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate return (status); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate int32_t 4487c478bd9Sstevel@tonic-gate psvc_update_setpoint_0(psvc_opaque_t hdlp, char *id) 4497c478bd9Sstevel@tonic-gate { 4507c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 4517c478bd9Sstevel@tonic-gate char *temp_sensor; 4527c478bd9Sstevel@tonic-gate int32_t match_count, i, temp; 4537c478bd9Sstevel@tonic-gate int16_t lowest_temp = 500; 4547c478bd9Sstevel@tonic-gate boolean_t present; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 4577c478bd9Sstevel@tonic-gate if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) 4587c478bd9Sstevel@tonic-gate return (status); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count, 4617c478bd9Sstevel@tonic-gate PSVC_DEV_TEMP_SENSOR); 4627c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 4637c478bd9Sstevel@tonic-gate return (status); 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate for (i = 0; i < match_count; i++) { 4667c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 4677c478bd9Sstevel@tonic-gate &temp_sensor, PSVC_DEV_TEMP_SENSOR, i); 4687c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 4697c478bd9Sstevel@tonic-gate return (status); 4707c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, temp_sensor, 4717c478bd9Sstevel@tonic-gate PSVC_OPTIMAL_TEMP_ATTR, &temp); 4727c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 4737c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Failed to get Optimal temp for %s\n", 4747c478bd9Sstevel@tonic-gate temp_sensor); 4757c478bd9Sstevel@tonic-gate return (status); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate if (temp < lowest_temp) 4787c478bd9Sstevel@tonic-gate lowest_temp = temp; 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_SETPOINT_ATTR, &lowest_temp); 4817c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 4827c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Failed to change setpoint for %s\n", id); 4837c478bd9Sstevel@tonic-gate return (status); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate return (status); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate int32_t 4897c478bd9Sstevel@tonic-gate psvc_remove_missing_nodes_0(psvc_opaque_t hdlp, char *id) 4907c478bd9Sstevel@tonic-gate { 4917c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 4927c478bd9Sstevel@tonic-gate char state[32]; 4937c478bd9Sstevel@tonic-gate char *physical_dev; 4947c478bd9Sstevel@tonic-gate int32_t i, device_count; 4957c478bd9Sstevel@tonic-gate char parent_path[256]; 4967c478bd9Sstevel@tonic-gate picl_nodehdl_t child_node; 4977c478bd9Sstevel@tonic-gate boolean_t present; 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 5007c478bd9Sstevel@tonic-gate &device_count, PSVC_PHYSICAL_DEVICE); 5017c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 5027c478bd9Sstevel@tonic-gate return (status); 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate for (i = 0; i < device_count; i++) { 5057c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 5067c478bd9Sstevel@tonic-gate &physical_dev, PSVC_PHYSICAL_DEVICE, i); 5077c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5087c478bd9Sstevel@tonic-gate return (status); 5097c478bd9Sstevel@tonic-gate if (strncmp(physical_dev, "LTC1427", 7) == 0) 5107c478bd9Sstevel@tonic-gate continue; 5117c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, physical_dev, 5127c478bd9Sstevel@tonic-gate PSVC_PROBE_RESULT_ATTR, state); 5137c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 5147c478bd9Sstevel@tonic-gate continue; 5157c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, physical_dev, PSVC_PRESENCE_ATTR, 5167c478bd9Sstevel@tonic-gate &present); 5177c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 5187c478bd9Sstevel@tonic-gate syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, physical_dev, 5197c478bd9Sstevel@tonic-gate errno); 5207c478bd9Sstevel@tonic-gate return (status); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if ((strcmp(state, PSVC_ERROR) == 0) && 5247c478bd9Sstevel@tonic-gate (present == PSVC_PRESENT)) { 5257c478bd9Sstevel@tonic-gate /* convert name to node, and parent path */ 5267c478bd9Sstevel@tonic-gate psvcplugin_lookup(physical_dev, parent_path, 5277c478bd9Sstevel@tonic-gate &child_node); 5287c478bd9Sstevel@tonic-gate /* Device removed */ 5297c478bd9Sstevel@tonic-gate ptree_delete_node(child_node); 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate return (status); 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate int32_t 5367c478bd9Sstevel@tonic-gate psvc_check_ps_hotplug_status_0(psvc_opaque_t hdlp, char *id) 5377c478bd9Sstevel@tonic-gate { 5387c478bd9Sstevel@tonic-gate char fail_valid_switch_id[PICL_PROPNAMELEN_MAX]; 5397c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 5407c478bd9Sstevel@tonic-gate char valid_switch_state[32]; 5417c478bd9Sstevel@tonic-gate char state[32], fault[32]; 5427c478bd9Sstevel@tonic-gate int32_t led_count, j; 5437c478bd9Sstevel@tonic-gate char *led_id; 5447c478bd9Sstevel@tonic-gate char led_state[32]; 5457c478bd9Sstevel@tonic-gate boolean_t present; 5467c478bd9Sstevel@tonic-gate static int8_t hotplug_failed_count = 0; 547*5eb92cf2Sdhain static int unplugged_ps = 0; 548298b7f4cSjfrank int retry; 549*5eb92cf2Sdhain char *unplugged_id; 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 5527c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 5537c478bd9Sstevel@tonic-gate syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, id, errno); 5547c478bd9Sstevel@tonic-gate return (status); 5557c478bd9Sstevel@tonic-gate } 5567c478bd9Sstevel@tonic-gate 5577c478bd9Sstevel@tonic-gate if (present == PSVC_ABSENT) { 5587c478bd9Sstevel@tonic-gate errno = ENODEV; 5597c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 5607c478bd9Sstevel@tonic-gate } 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate snprintf(fail_valid_switch_id, sizeof (fail_valid_switch_id), "%s%s", 5637c478bd9Sstevel@tonic-gate id, "_SENSOR_VALID_SWITCH"); 5647c478bd9Sstevel@tonic-gate 5657c478bd9Sstevel@tonic-gate retry = 0; 5667c478bd9Sstevel@tonic-gate do { 5677c478bd9Sstevel@tonic-gate if (retry) 568298b7f4cSjfrank (void) sleep(retry_sleep_pshp_status); 5697c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fail_valid_switch_id, 5707c478bd9Sstevel@tonic-gate PSVC_STATE_ATTR, valid_switch_state); 5717c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 5727c478bd9Sstevel@tonic-gate if (hotplug_failed_count == 0) { 5737c478bd9Sstevel@tonic-gate /* 5747c478bd9Sstevel@tonic-gate * First time the get_attr call failed 5757c478bd9Sstevel@tonic-gate * set count so that if we fail again 5767c478bd9Sstevel@tonic-gate * we will know 5777c478bd9Sstevel@tonic-gate */ 5787c478bd9Sstevel@tonic-gate hotplug_failed_count = 1; 5797c478bd9Sstevel@tonic-gate /* 5807c478bd9Sstevel@tonic-gate * We probably failed because the power 5817c478bd9Sstevel@tonic-gate * supply was just insterted or removed 5827c478bd9Sstevel@tonic-gate * before the get_attr call. We then 5837c478bd9Sstevel@tonic-gate * return from this policy successfully 5847c478bd9Sstevel@tonic-gate * knowing it will be run again shortly 5857c478bd9Sstevel@tonic-gate * with the right PS state. 5867c478bd9Sstevel@tonic-gate */ 5877c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 5887c478bd9Sstevel@tonic-gate } else { 5897c478bd9Sstevel@tonic-gate /* 5907c478bd9Sstevel@tonic-gate * We have failed before and so this 5917c478bd9Sstevel@tonic-gate * we will consider a hardware problem 5927c478bd9Sstevel@tonic-gate * and it should be reported 5937c478bd9Sstevel@tonic-gate */ 5947c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 5957c478bd9Sstevel@tonic-gate "Failed getting %s State: ", 5967c478bd9Sstevel@tonic-gate "ps_hotplug_status_0\n", 5977c478bd9Sstevel@tonic-gate fail_valid_switch_id); 5987c478bd9Sstevel@tonic-gate return (status); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate /* 6027c478bd9Sstevel@tonic-gate * Because we have successfully gotten a value from 6037c478bd9Sstevel@tonic-gate * the i2c device on the PS we will set the 6047c478bd9Sstevel@tonic-gate * failed_count to 0 6057c478bd9Sstevel@tonic-gate */ 6067c478bd9Sstevel@tonic-gate hotplug_failed_count = 0; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state); 6097c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 6107c478bd9Sstevel@tonic-gate return (status); 6117c478bd9Sstevel@tonic-gate retry++; 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * check to see if we need to retry. the conditions are: 6147c478bd9Sstevel@tonic-gate * 6157c478bd9Sstevel@tonic-gate * valid_switch_state state retry 6167c478bd9Sstevel@tonic-gate * -------------------------------------------------- 6177c478bd9Sstevel@tonic-gate * PSVC_OFF !PSVC_HOTPLUGGED yes 6187c478bd9Sstevel@tonic-gate * PSVC_ON PSVC_HOTPLUGGED yes 6197c478bd9Sstevel@tonic-gate * PSVC_OFF PSVC_HOTPLUGGED no 6207c478bd9Sstevel@tonic-gate * PSVC_ON !PSVC_HOTPLUGGED no 6217c478bd9Sstevel@tonic-gate */ 622298b7f4cSjfrank } while ((retry < n_retry_pshp_status) && 6237c478bd9Sstevel@tonic-gate change_of_state_str(valid_switch_state, PSVC_OFF, 6247c478bd9Sstevel@tonic-gate state, PSVC_HOTPLUGGED)); 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate if ((strcmp(valid_switch_state, PSVC_OFF) == 0) && 627*5eb92cf2Sdhain (strcmp(state, PSVC_HOTPLUGGED) != 0)) { 6287c478bd9Sstevel@tonic-gate strcpy(state, PSVC_HOTPLUGGED); 6297c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 6307c478bd9Sstevel@tonic-gate strcpy(led_state, PSVC_LED_OFF); 6317c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 632*5eb92cf2Sdhain state); 6337c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 6347c478bd9Sstevel@tonic-gate return (status); 6357c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 636*5eb92cf2Sdhain &led_count, PSVC_DEV_FAULT_LED); 6377c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 6387c478bd9Sstevel@tonic-gate return (status); 6397c478bd9Sstevel@tonic-gate 6407c478bd9Sstevel@tonic-gate for (j = 0; j < led_count; j++) { 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 643*5eb92cf2Sdhain &led_id, PSVC_DEV_FAULT_LED, j); 6447c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 6457c478bd9Sstevel@tonic-gate return (status); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 648*5eb92cf2Sdhain PSVC_LED_STATE_ATTR, led_state); 6497c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 6507c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, 6517c478bd9Sstevel@tonic-gate errno); 6527c478bd9Sstevel@tonic-gate return (status); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate } 656*5eb92cf2Sdhain strcpy(led_state, PSVC_LED_ON); 657*5eb92cf2Sdhain status = psvc_set_attr(hdlp, "FSP_POWER_FAULT_LED", 658*5eb92cf2Sdhain PSVC_LED_STATE_ATTR, led_state); 659*5eb92cf2Sdhain if (status != PSVC_SUCCESS) { 660*5eb92cf2Sdhain syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, errno); 661*5eb92cf2Sdhain return (status); 662*5eb92cf2Sdhain } 663*5eb92cf2Sdhain unplugged_id = id + 2; 664*5eb92cf2Sdhain unplugged_ps = unplugged_ps | (1 << (int)strtol(unplugged_id, 665*5eb92cf2Sdhain (char **)NULL, 10)); 666*5eb92cf2Sdhain status = update_gen_fault_led(hdlp, GEN_FAULT_LED); 6677c478bd9Sstevel@tonic-gate syslog(LOG_ERR, PS_UNPLUGGED_MSG, id); 6687c478bd9Sstevel@tonic-gate return (status); 6697c478bd9Sstevel@tonic-gate } 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate if ((strcmp(valid_switch_state, PSVC_ON) == 0) && 672*5eb92cf2Sdhain (strcmp(state, PSVC_HOTPLUGGED) == 0)) { 6737c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 6747c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 6757c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 6767c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 6777c478bd9Sstevel@tonic-gate return (status); 678*5eb92cf2Sdhain unplugged_id = id + 2; 679*5eb92cf2Sdhain unplugged_ps = unplugged_ps ^ (1 << (int)strtol(unplugged_id, 680*5eb92cf2Sdhain (char **)NULL, 10)); 681*5eb92cf2Sdhain if (unplugged_ps == 0) { 682*5eb92cf2Sdhain strcpy(led_state, PSVC_LED_OFF); 683*5eb92cf2Sdhain status = psvc_set_attr(hdlp, "FSP_POWER_FAULT_LED", 684*5eb92cf2Sdhain PSVC_LED_STATE_ATTR, led_state); 685*5eb92cf2Sdhain if (status != PSVC_SUCCESS) { 686*5eb92cf2Sdhain syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, 687*5eb92cf2Sdhain errno); 688*5eb92cf2Sdhain return (status); 689*5eb92cf2Sdhain } 690*5eb92cf2Sdhain status = update_gen_fault_led(hdlp, GEN_FAULT_LED); 691*5eb92cf2Sdhain } 6927c478bd9Sstevel@tonic-gate syslog(LOG_ERR, PS_PLUGGED_MSG, id); 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate return (status); 6967c478bd9Sstevel@tonic-gate } 6977c478bd9Sstevel@tonic-gate 6987c478bd9Sstevel@tonic-gate int32_t 6997c478bd9Sstevel@tonic-gate psvc_ps_overcurrent_check_policy_0(psvc_opaque_t hdlp, char *system) 7007c478bd9Sstevel@tonic-gate { 7017c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 7027c478bd9Sstevel@tonic-gate boolean_t present; 7037c478bd9Sstevel@tonic-gate static char *sensor_id[DAKTARI_MAX_PS][DAK_MAX_PS_I_SENSORS]; 704360e6f5eSmathue static char *power_supply_id[DAKTARI_MAX_PS] = {NULL}; 7057c478bd9Sstevel@tonic-gate int32_t i, j; 7067c478bd9Sstevel@tonic-gate int32_t amps, oc_flag = 0, ps_present = 0; 7077c478bd9Sstevel@tonic-gate static int32_t hi_warn[DAKTARI_MAX_PS][DAK_MAX_PS_I_SENSORS]; 7087c478bd9Sstevel@tonic-gate char state[32]; 7097c478bd9Sstevel@tonic-gate static int8_t overcurrent_failed_check = 0; 710298b7f4cSjfrank static int threshold_counter = 0; 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate if (power_supply_id[0] == NULL) { 7137c478bd9Sstevel@tonic-gate for (i = 0; i < DAKTARI_MAX_PS; i++) { 7147c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, system, 7157c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &(power_supply_id[i]), 7167c478bd9Sstevel@tonic-gate PSVC_PS, i); 7177c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7187c478bd9Sstevel@tonic-gate return (status); 7197c478bd9Sstevel@tonic-gate for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) { 7207c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, 7217c478bd9Sstevel@tonic-gate power_supply_id[i], PSVC_ASSOC_ID_ATTR, 7227c478bd9Sstevel@tonic-gate &(sensor_id[i][j]), PSVC_PS_I_SENSOR, j); 7237c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7247c478bd9Sstevel@tonic-gate return (status); 7257c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id[i][j], 7267c478bd9Sstevel@tonic-gate PSVC_HI_WARN_ATTR, &(hi_warn[i][j])); 7277c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 7287c478bd9Sstevel@tonic-gate return (status); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate 7337c478bd9Sstevel@tonic-gate for (i = 0; i < DAKTARI_MAX_PS; i++) { 7347c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, power_supply_id[i], 735*5eb92cf2Sdhain PSVC_PRESENCE_ATTR, &present); 7367c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 7377c478bd9Sstevel@tonic-gate syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, 738*5eb92cf2Sdhain power_supply_id[i], errno); 7397c478bd9Sstevel@tonic-gate return (status); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate if (present == PSVC_ABSENT) { 7437c478bd9Sstevel@tonic-gate continue; 7447c478bd9Sstevel@tonic-gate } 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate status = psvc_check_ps_hotplug_status_0(hdlp, 7477c478bd9Sstevel@tonic-gate power_supply_id[i]); 7487c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 7497c478bd9Sstevel@tonic-gate return (status); 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, power_supply_id[i], 7527c478bd9Sstevel@tonic-gate PSVC_STATE_ATTR, state); 7537c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 7547c478bd9Sstevel@tonic-gate return (status); 7557c478bd9Sstevel@tonic-gate 7567c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_HOTPLUGGED) == 0) { 7577c478bd9Sstevel@tonic-gate continue; 7587c478bd9Sstevel@tonic-gate } else { 7597c478bd9Sstevel@tonic-gate ps_present++; 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) { 7637c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id[i][j], 764*5eb92cf2Sdhain PSVC_SENSOR_VALUE_ATTR, &s); 7657c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 7667c478bd9Sstevel@tonic-gate if (overcurrent_failed_check == 0) { 7677c478bd9Sstevel@tonic-gate /* 7687c478bd9Sstevel@tonic-gate * First time the get_attr call 7697c478bd9Sstevel@tonic-gate * failed set count so that if we 7707c478bd9Sstevel@tonic-gate * fail again we will know 7717c478bd9Sstevel@tonic-gate */ 7727c478bd9Sstevel@tonic-gate overcurrent_failed_check = 1; 7737c478bd9Sstevel@tonic-gate /* 7747c478bd9Sstevel@tonic-gate * We probably failed because the power 7757c478bd9Sstevel@tonic-gate * supply was just insterted or removed 7767c478bd9Sstevel@tonic-gate * before the get_attr call. We then 7777c478bd9Sstevel@tonic-gate * return from this policy successfully 7787c478bd9Sstevel@tonic-gate * knowing it will be run again shortly 7797c478bd9Sstevel@tonic-gate * with the right PS state. 7807c478bd9Sstevel@tonic-gate */ 7817c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 7827c478bd9Sstevel@tonic-gate } else { 7837c478bd9Sstevel@tonic-gate /* 7847c478bd9Sstevel@tonic-gate * We have failed before and so this we 7857c478bd9Sstevel@tonic-gate * will consider a hardware problem and 7867c478bd9Sstevel@tonic-gate * it should be reported. 7877c478bd9Sstevel@tonic-gate */ 7887c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 7897c478bd9Sstevel@tonic-gate "Failed getting %s sensor value", 7907c478bd9Sstevel@tonic-gate sensor_id[i][j]); 7917c478bd9Sstevel@tonic-gate return (status); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate /* 7957c478bd9Sstevel@tonic-gate * Because we have successfully gotten a value from the 7967c478bd9Sstevel@tonic-gate * i2c device on the PS we will set the failed_count 7977c478bd9Sstevel@tonic-gate * to 0. 7987c478bd9Sstevel@tonic-gate */ 7997c478bd9Sstevel@tonic-gate overcurrent_failed_check = 0; 8007c478bd9Sstevel@tonic-gate 8017c478bd9Sstevel@tonic-gate if (amps >= hi_warn[i][j]) { 8027c478bd9Sstevel@tonic-gate oc_flag = 1; 8037c478bd9Sstevel@tonic-gate } 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate } 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate if (oc_flag) { 8087c478bd9Sstevel@tonic-gate /* 8097c478bd9Sstevel@tonic-gate * Because we observed an overcurrent 8107c478bd9Sstevel@tonic-gate * condition, we increment threshold_counter. 8117c478bd9Sstevel@tonic-gate * Once threshold_counter reaches the value 812298b7f4cSjfrank * of n_read_overcurrent we log the event. 8137c478bd9Sstevel@tonic-gate */ 8147c478bd9Sstevel@tonic-gate threshold_counter++; 815298b7f4cSjfrank if (threshold_counter == n_read_overcurrent) { 8167c478bd9Sstevel@tonic-gate threshold_counter = 0; 8177c478bd9Sstevel@tonic-gate if (ps_present == 1) { 8187c478bd9Sstevel@tonic-gate syslog(LOG_ERR, PS_OVER_CURRENT_MSG); 8197c478bd9Sstevel@tonic-gate syslog(LOG_ERR, ADD_PS_MSG); 8207c478bd9Sstevel@tonic-gate } else { 8217c478bd9Sstevel@tonic-gate syslog(LOG_ERR, PS_OVER_CURRENT_MSG); 8227c478bd9Sstevel@tonic-gate syslog(LOG_ERR, REMOVE_LOAD_MSG); 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate } else { 8267c478bd9Sstevel@tonic-gate threshold_counter = 0; 8277c478bd9Sstevel@tonic-gate } 8287c478bd9Sstevel@tonic-gate 8297c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 8307c478bd9Sstevel@tonic-gate } 8317c478bd9Sstevel@tonic-gate 8327c478bd9Sstevel@tonic-gate int32_t 8337c478bd9Sstevel@tonic-gate psvc_ps_device_fail_notifier_policy_0(psvc_opaque_t hdlp, char *system) 8347c478bd9Sstevel@tonic-gate { 835360e6f5eSmathue static char *ps_id[DAKTARI_MAX_PS] = {NULL}; 8367c478bd9Sstevel@tonic-gate static char *sensor_id[DAKTARI_MAX_PS][DAK_MAX_FAULT_SENSORS]; 8377c478bd9Sstevel@tonic-gate char *led_id = "FSP_POWER_FAULT_LED"; 8387c478bd9Sstevel@tonic-gate int i, j; 8397c478bd9Sstevel@tonic-gate char state[32], fault[32], previous_state[32], past_state[32]; 8407c478bd9Sstevel@tonic-gate char led_state[32]; 8417c478bd9Sstevel@tonic-gate char bad_sensors[DAK_MAX_FAULT_SENSORS][256]; 8427c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 8437c478bd9Sstevel@tonic-gate boolean_t present; 8447c478bd9Sstevel@tonic-gate int fail_state; 8457c478bd9Sstevel@tonic-gate static int8_t device_fail_failed_check = 0; 846298b7f4cSjfrank int retry, should_retry; 8477c478bd9Sstevel@tonic-gate 8487c478bd9Sstevel@tonic-gate if (ps_id[0] == NULL) { 8497c478bd9Sstevel@tonic-gate for (i = 0; i < DAKTARI_MAX_PS; i++) { 8507c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, system, 8517c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &(ps_id[i]), PSVC_PS, i); 8527c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 8537c478bd9Sstevel@tonic-gate return (status); 8547c478bd9Sstevel@tonic-gate for (j = 0; j < DAK_MAX_FAULT_SENSORS; j++) { 8557c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, ps_id[i], 8567c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &(sensor_id[i][j]), 8577c478bd9Sstevel@tonic-gate PSVC_DEV_FAULT_SENSOR, j); 8587c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 8597c478bd9Sstevel@tonic-gate return (status); 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate } 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate 8647c478bd9Sstevel@tonic-gate for (i = 0; i < DAKTARI_MAX_PS; i++) { 8657c478bd9Sstevel@tonic-gate fail_state = 0; 8667c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, ps_id[i], PSVC_PRESENCE_ATTR, 8677c478bd9Sstevel@tonic-gate &present); 8687c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 8697c478bd9Sstevel@tonic-gate return (status); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate if (present == PSVC_ABSENT) { 8727c478bd9Sstevel@tonic-gate errno = ENODEV; 8737c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate status = psvc_check_ps_hotplug_status_0(hdlp, ps_id[i]); 8777c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 8787c478bd9Sstevel@tonic-gate return (status); 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, ps_id[i], PSVC_STATE_ATTR, 8817c478bd9Sstevel@tonic-gate past_state); 8827c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 8837c478bd9Sstevel@tonic-gate return (status); 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate if (strcmp(past_state, PSVC_HOTPLUGGED) == 0) { 8867c478bd9Sstevel@tonic-gate return (PICL_SUCCESS); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate retry = 0; 8907c478bd9Sstevel@tonic-gate do { 8917c478bd9Sstevel@tonic-gate if (retry) 892298b7f4cSjfrank (void) sleep(retry_sleep_devicefail); 8937c478bd9Sstevel@tonic-gate fail_state = 0; 8947c478bd9Sstevel@tonic-gate should_retry = 0; 8957c478bd9Sstevel@tonic-gate for (j = 0; j < DAK_MAX_FAULT_SENSORS; ++j) { 8967c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id[i][j], 8977c478bd9Sstevel@tonic-gate PSVC_SWITCH_STATE_ATTR, state); 8987c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 8997c478bd9Sstevel@tonic-gate if (device_fail_failed_check == 0) { 9007c478bd9Sstevel@tonic-gate /* 9017c478bd9Sstevel@tonic-gate * First time the get_attr call 9027c478bd9Sstevel@tonic-gate * failed set count so that 9037c478bd9Sstevel@tonic-gate * if we fail again we will know 9047c478bd9Sstevel@tonic-gate */ 9057c478bd9Sstevel@tonic-gate device_fail_failed_check = 1; 9067c478bd9Sstevel@tonic-gate /* 9077c478bd9Sstevel@tonic-gate * We probably failed because 9087c478bd9Sstevel@tonic-gate * the power supply was just 9097c478bd9Sstevel@tonic-gate * insterted or removed before 9107c478bd9Sstevel@tonic-gate * the get_attr call. We then 9117c478bd9Sstevel@tonic-gate * return from this policy 9127c478bd9Sstevel@tonic-gate * successfully knowing it will 9137c478bd9Sstevel@tonic-gate * be run again shortly 9147c478bd9Sstevel@tonic-gate * with the right PS state. 9157c478bd9Sstevel@tonic-gate */ 9167c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 9177c478bd9Sstevel@tonic-gate } else { 9187c478bd9Sstevel@tonic-gate /* 9197c478bd9Sstevel@tonic-gate * We have failed before and 9207c478bd9Sstevel@tonic-gate * so this we will consider a 9217c478bd9Sstevel@tonic-gate * hardware problem and 9227c478bd9Sstevel@tonic-gate * it should be reported. 9237c478bd9Sstevel@tonic-gate */ 9247c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "Failed in " 9257c478bd9Sstevel@tonic-gate "getting sensor state for " 9267c478bd9Sstevel@tonic-gate "%s\n", sensor_id[i][j]); 9277c478bd9Sstevel@tonic-gate 9287c478bd9Sstevel@tonic-gate return (status); 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate 9327c478bd9Sstevel@tonic-gate /* 9337c478bd9Sstevel@tonic-gate * Because we have successfully gotten 9347c478bd9Sstevel@tonic-gate * a value from the i2c device on the 9357c478bd9Sstevel@tonic-gate * PS we will set the failed_count to 0. 9367c478bd9Sstevel@tonic-gate */ 9377c478bd9Sstevel@tonic-gate device_fail_failed_check = 0; 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate /* 9407c478bd9Sstevel@tonic-gate * If we find that the sensor is on we 9417c478bd9Sstevel@tonic-gate * fill in the name of the sensor in 9427c478bd9Sstevel@tonic-gate * the bad_sensor array. If the sensor 9437c478bd9Sstevel@tonic-gate * is off we use EMPTY_STRING as a check 9447c478bd9Sstevel@tonic-gate * later on as to when NOT to print out 9457c478bd9Sstevel@tonic-gate * what is in bad_sensor[]. 9467c478bd9Sstevel@tonic-gate */ 9477c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_SWITCH_ON) == 0) { 9487c478bd9Sstevel@tonic-gate fail_state++; 9497c478bd9Sstevel@tonic-gate strlcpy(bad_sensors[j], sensor_id[i][j], 9507c478bd9Sstevel@tonic-gate sizeof (bad_sensors[j])); 9517c478bd9Sstevel@tonic-gate } else { 9527c478bd9Sstevel@tonic-gate strcpy(bad_sensors[j], EMPTY_STRING); 9537c478bd9Sstevel@tonic-gate } 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate retry++; 9567c478bd9Sstevel@tonic-gate /* 9577c478bd9Sstevel@tonic-gate * check to see if we need to retry. the conditions are: 9587c478bd9Sstevel@tonic-gate * 9597c478bd9Sstevel@tonic-gate * fail_state past_state retry 9607c478bd9Sstevel@tonic-gate * -------------------------------------------------- 9617c478bd9Sstevel@tonic-gate * + PSVC_OK yes 9627c478bd9Sstevel@tonic-gate * 0 PSVC_ERROR yes 9637c478bd9Sstevel@tonic-gate * + PSVC_ERROR no 9647c478bd9Sstevel@tonic-gate * 0 PSVC_OK no 9657c478bd9Sstevel@tonic-gate */ 9667c478bd9Sstevel@tonic-gate if ((fail_state > 0) && 9677c478bd9Sstevel@tonic-gate (strcmp(past_state, PSVC_OK) == 0)) { 9687c478bd9Sstevel@tonic-gate should_retry = 1; 9697c478bd9Sstevel@tonic-gate } else if ((fail_state == 0) && 9707c478bd9Sstevel@tonic-gate (strcmp(past_state, PSVC_ERROR) == 0)) { 9717c478bd9Sstevel@tonic-gate should_retry = 1; 9727c478bd9Sstevel@tonic-gate } 973298b7f4cSjfrank } while ((retry < n_retry_devicefail) && should_retry); 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate if (fail_state != 0) { 9767c478bd9Sstevel@tonic-gate strcpy(state, PSVC_ERROR); 9777c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_GEN_FAULT); 9787c478bd9Sstevel@tonic-gate } else { 9797c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 9807c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, ps_id[i], PSVC_STATE_ATTR, state); 9847c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 9857c478bd9Sstevel@tonic-gate return (status); 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, ps_id[i], PSVC_FAULTID_ATTR, 9887c478bd9Sstevel@tonic-gate fault); 9897c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 9907c478bd9Sstevel@tonic-gate return (status); 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, ps_id[i], PSVC_PREV_STATE_ATTR, 9937c478bd9Sstevel@tonic-gate previous_state); 9947c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 9957c478bd9Sstevel@tonic-gate return (status); 9967c478bd9Sstevel@tonic-gate 9977c478bd9Sstevel@tonic-gate if (strcmp(state, previous_state) != 0) { 9987c478bd9Sstevel@tonic-gate char dev_label[32]; 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, ps_id[i], PSVC_LABEL_ATTR, 10017c478bd9Sstevel@tonic-gate dev_label); 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_ERROR) == 0) { 10047c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_FAILURE_MSG, dev_label); 10057c478bd9Sstevel@tonic-gate for (j = 0; j < DAK_MAX_FAULT_SENSORS; ++j) { 10067c478bd9Sstevel@tonic-gate if (strcmp(bad_sensors[j], 1007*5eb92cf2Sdhain EMPTY_STRING) != 0) 10087c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "%s\n", 10097c478bd9Sstevel@tonic-gate bad_sensors[j]); 10107c478bd9Sstevel@tonic-gate } 10117c478bd9Sstevel@tonic-gate strcpy(led_state, PSVC_LED_ON); 10127c478bd9Sstevel@tonic-gate } else { 10137c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_OK_MSG, dev_label); 10147c478bd9Sstevel@tonic-gate strcpy(led_state, PSVC_LED_OFF); 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 10187c478bd9Sstevel@tonic-gate PSVC_LED_STATE_ATTR, led_state); 10197c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 10207c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, 10217c478bd9Sstevel@tonic-gate errno); 10227c478bd9Sstevel@tonic-gate return (status); 10237c478bd9Sstevel@tonic-gate } 10247c478bd9Sstevel@tonic-gate } 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 10287c478bd9Sstevel@tonic-gate } 10297c478bd9Sstevel@tonic-gate 10307c478bd9Sstevel@tonic-gate int32_t 10317c478bd9Sstevel@tonic-gate psvc_ps_check_and_disable_dr_policy_0(psvc_opaque_t hdlp, char *id) 10327c478bd9Sstevel@tonic-gate { 10337c478bd9Sstevel@tonic-gate char state[32]; 1034360e6f5eSmathue static char *name[DAKTARI_MAX_PS] = {NULL}; 10357c478bd9Sstevel@tonic-gate int ps_cnt = 0; 10367c478bd9Sstevel@tonic-gate int i, j; 10377c478bd9Sstevel@tonic-gate int dr_conf; 10387c478bd9Sstevel@tonic-gate int fd, rv; 10397c478bd9Sstevel@tonic-gate boolean_t present; 10407c478bd9Sstevel@tonic-gate char dev_path[sizeof (HPC3130_DEV)+8]; 10417c478bd9Sstevel@tonic-gate unsigned char controller_names[HPC3130_CONTROLLERS] = 10427c478bd9Sstevel@tonic-gate { 0xe2, 0xe6, 0xe8, 0xec }; 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate if (name[0] == NULL) { 10457c478bd9Sstevel@tonic-gate for (i = 0; i < DAKTARI_MAX_PS; i++) { 10467c478bd9Sstevel@tonic-gate rv = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 10477c478bd9Sstevel@tonic-gate &(name[i]), PSVC_PS, i); 10487c478bd9Sstevel@tonic-gate if (rv != PSVC_SUCCESS) 10497c478bd9Sstevel@tonic-gate return (rv); 10507c478bd9Sstevel@tonic-gate } 10517c478bd9Sstevel@tonic-gate } 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate /* 10547c478bd9Sstevel@tonic-gate * Go through the power supplies to make sure they're present 10557c478bd9Sstevel@tonic-gate * and OK. 10567c478bd9Sstevel@tonic-gate */ 10577c478bd9Sstevel@tonic-gate ps_cnt = DAKTARI_MAX_PS; 10587c478bd9Sstevel@tonic-gate for (i = 0; i < DAKTARI_MAX_PS; i++) { 10597c478bd9Sstevel@tonic-gate rv = psvc_get_attr(hdlp, name[i], PSVC_PRESENCE_ATTR, 10607c478bd9Sstevel@tonic-gate &present); 10617c478bd9Sstevel@tonic-gate if (rv != PSVC_SUCCESS) 10627c478bd9Sstevel@tonic-gate return (rv); 10637c478bd9Sstevel@tonic-gate 10647c478bd9Sstevel@tonic-gate if (present != PSVC_PRESENT) { 10657c478bd9Sstevel@tonic-gate ps_cnt--; 10667c478bd9Sstevel@tonic-gate continue; 10677c478bd9Sstevel@tonic-gate } else { 10687c478bd9Sstevel@tonic-gate rv = psvc_get_attr(hdlp, name[i], PSVC_STATE_ATTR, 1069*5eb92cf2Sdhain state); 10707c478bd9Sstevel@tonic-gate if (rv != PSVC_SUCCESS) 10717c478bd9Sstevel@tonic-gate return (rv); 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_OK)) 10747c478bd9Sstevel@tonic-gate ps_cnt--; 10757c478bd9Sstevel@tonic-gate } 10767c478bd9Sstevel@tonic-gate } 10777c478bd9Sstevel@tonic-gate 10787c478bd9Sstevel@tonic-gate /* 10797c478bd9Sstevel@tonic-gate * No change in DR configuration is needed if the new power supply 10807c478bd9Sstevel@tonic-gate * count equals the current count. 10817c478bd9Sstevel@tonic-gate */ 10827c478bd9Sstevel@tonic-gate if (ps_cnt == co_ps) 10837c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 10847c478bd9Sstevel@tonic-gate 10857c478bd9Sstevel@tonic-gate /* 10867c478bd9Sstevel@tonic-gate * Disable DR when hotplugged down to 1 power supply; enable DR when 10877c478bd9Sstevel@tonic-gate * hotplugged up from 1 supply. 10887c478bd9Sstevel@tonic-gate */ 10897c478bd9Sstevel@tonic-gate assert(ps_cnt); 10907c478bd9Sstevel@tonic-gate if ((co_ps == 0 || co_ps > 1) && ps_cnt != 1) { 10917c478bd9Sstevel@tonic-gate co_ps = ps_cnt; 10927c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate dr_conf = (ps_cnt == 1 ? HPC3130_DR_DISABLE : HPC3130_DR_ENABLE); 10957c478bd9Sstevel@tonic-gate co_ps = ps_cnt; 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate for (i = 0; i < HPC3130_CONTROLLERS; i++) { 10987c478bd9Sstevel@tonic-gate for (j = 0; j < HPC3130_SLOTS; j++) { 10997c478bd9Sstevel@tonic-gate (void) snprintf(dev_path, sizeof (dev_path), 11007c478bd9Sstevel@tonic-gate HPC3130_DEV, controller_names[i], j); 11017c478bd9Sstevel@tonic-gate fd = open(dev_path, O_RDWR); 11027c478bd9Sstevel@tonic-gate if (fd == -1) 11037c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate rv = ioctl(fd, HPC3130_CONF_DR, &dr_conf); 11067c478bd9Sstevel@tonic-gate close(fd); 11077c478bd9Sstevel@tonic-gate if (rv == -1) 11087c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 11097c478bd9Sstevel@tonic-gate } 11107c478bd9Sstevel@tonic-gate } 11117c478bd9Sstevel@tonic-gate 11127c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate int32_t 11167c478bd9Sstevel@tonic-gate psvc_fan_blast_shutoff_policy_0(psvc_opaque_t hdlp, char *id) 11177c478bd9Sstevel@tonic-gate { 11187c478bd9Sstevel@tonic-gate char switch_status[32]; 11197c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 11207c478bd9Sstevel@tonic-gate 11217c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, switch_status); 11227c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 11237c478bd9Sstevel@tonic-gate return (status); 11247c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, 1125*5eb92cf2Sdhain PSVC_SWITCH_OFF); 11267c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 11277c478bd9Sstevel@tonic-gate return (status); 11287c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, 1129*5eb92cf2Sdhain PSVC_SWITCH_ON); 11307c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 11317c478bd9Sstevel@tonic-gate return (status); 11327c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, 1133*5eb92cf2Sdhain PSVC_SWITCH_OFF); 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate return (status); 11367c478bd9Sstevel@tonic-gate } 11377c478bd9Sstevel@tonic-gate 11387c478bd9Sstevel@tonic-gate int32_t 11397c478bd9Sstevel@tonic-gate psvc_fan_fault_check_policy_0(psvc_opaque_t hdlp, char *system) 11407c478bd9Sstevel@tonic-gate { 1141360e6f5eSmathue static char *fan_id[DAK_MAX_FANS] = {NULL}; 11427c478bd9Sstevel@tonic-gate boolean_t enabled; 11437c478bd9Sstevel@tonic-gate int32_t speed; 11447c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 11457c478bd9Sstevel@tonic-gate int r; 1146298b7f4cSjfrank static int threshold_counter = 0; 11477c478bd9Sstevel@tonic-gate 11487c478bd9Sstevel@tonic-gate if (fan_id[0] == NULL) { 11497c478bd9Sstevel@tonic-gate for (r = 0; r < DAK_MAX_FANS; r++) { 11507c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, system, 11517c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &(fan_id[r]), PSVC_FAN, r); 11527c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 11537c478bd9Sstevel@tonic-gate return (status); 11547c478bd9Sstevel@tonic-gate } 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate for (r = 0; r < DAK_MAX_FANS; r++) { 11587c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fan_id[r], PSVC_ENABLE_ATTR, 11597c478bd9Sstevel@tonic-gate &enabled); 11607c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 11617c478bd9Sstevel@tonic-gate return (status); 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate if (enabled == PSVC_ENABLED) { 11647c478bd9Sstevel@tonic-gate uint64_t features; 11657c478bd9Sstevel@tonic-gate char *switch_id; 11667c478bd9Sstevel@tonic-gate char switch_state[32], fan_state[32]; 11677c478bd9Sstevel@tonic-gate int fan_count, fans; 11687c478bd9Sstevel@tonic-gate char *other_fan_id; 11697c478bd9Sstevel@tonic-gate char fstate[32], ffault[32]; 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate /* 11727c478bd9Sstevel@tonic-gate * If any other fan on the fan tray has an ERROR state, 11737c478bd9Sstevel@tonic-gate * mark this fan bad and return 11747c478bd9Sstevel@tonic-gate */ 11757c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, fan_id[r], PSVC_ASSOC_MATCHES_ATTR, 11767c478bd9Sstevel@tonic-gate &fan_count, PSVC_FAN_TRAY_FANS); 11777c478bd9Sstevel@tonic-gate for (fans = 0; fans < fan_count; ++fans) { 11787c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fan_id[r], 11797c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &other_fan_id, 11807c478bd9Sstevel@tonic-gate PSVC_FAN_TRAY_FANS, fans); 11817c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 11827c478bd9Sstevel@tonic-gate return (status); 11837c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, other_fan_id, 11847c478bd9Sstevel@tonic-gate PSVC_STATE_ATTR, fan_state); 11857c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 11867c478bd9Sstevel@tonic-gate return (status); 11877c478bd9Sstevel@tonic-gate 11887c478bd9Sstevel@tonic-gate if (strcmp(fan_state, PSVC_ERROR) == 0) { 11897c478bd9Sstevel@tonic-gate strlcpy(ffault, PSVC_GEN_FAULT, 11907c478bd9Sstevel@tonic-gate sizeof (ffault)); 11917c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, fan_id[r], 11927c478bd9Sstevel@tonic-gate PSVC_FAULTID_ATTR, ffault); 11937c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 11947c478bd9Sstevel@tonic-gate return (status); 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate strlcpy(fstate, PSVC_ERROR, 11977c478bd9Sstevel@tonic-gate sizeof (fstate)); 11987c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, fan_id[r], 11997c478bd9Sstevel@tonic-gate PSVC_STATE_ATTR, fstate); 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate return (status); 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate /* 12067c478bd9Sstevel@tonic-gate * Select tachometer for IO or CPU primary/secondary 12077c478bd9Sstevel@tonic-gate * fans. 12087c478bd9Sstevel@tonic-gate */ 12097c478bd9Sstevel@tonic-gate pthread_mutex_lock(&fan_mutex); 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fan_id[r], 12127c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &switch_id, 12137c478bd9Sstevel@tonic-gate PSVC_FAN_PRIM_SEC_SELECTOR, 0); 12147c478bd9Sstevel@tonic-gate 12157c478bd9Sstevel@tonic-gate if (status != PSVC_FAILURE) { 12167c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fan_id[r], 12177c478bd9Sstevel@tonic-gate PSVC_FEATURES_ATTR, &features); 12187c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 12197c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex); 12207c478bd9Sstevel@tonic-gate return (status); 12217c478bd9Sstevel@tonic-gate } 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate if (features & PSVC_DEV_PRIMARY) 12247c478bd9Sstevel@tonic-gate strlcpy(switch_state, PSVC_SWITCH_ON, 12257c478bd9Sstevel@tonic-gate sizeof (switch_state)); 12267c478bd9Sstevel@tonic-gate else 12277c478bd9Sstevel@tonic-gate strlcpy(switch_state, PSVC_SWITCH_OFF, 12287c478bd9Sstevel@tonic-gate sizeof (switch_state)); 12297c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, switch_id, 12307c478bd9Sstevel@tonic-gate PSVC_SWITCH_STATE_ATTR, switch_state); 12317c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 12327c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex); 12337c478bd9Sstevel@tonic-gate return (status); 12347c478bd9Sstevel@tonic-gate } 12357c478bd9Sstevel@tonic-gate 12367c478bd9Sstevel@tonic-gate /* allow time for speed to be determined */ 12377c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, 250); 12387c478bd9Sstevel@tonic-gate } 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fan_id[r], 12417c478bd9Sstevel@tonic-gate PSVC_SENSOR_VALUE_ATTR, &speed); 12427c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 12437c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex); 12447c478bd9Sstevel@tonic-gate return (status); 12457c478bd9Sstevel@tonic-gate } 12467c478bd9Sstevel@tonic-gate 12477c478bd9Sstevel@tonic-gate pthread_mutex_unlock(&fan_mutex); 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate if (speed == 0) { 12507c478bd9Sstevel@tonic-gate threshold_counter++; 12517c478bd9Sstevel@tonic-gate if (threshold_counter == 1252298b7f4cSjfrank n_read_fanfault) { 12537c478bd9Sstevel@tonic-gate int32_t i; 12547c478bd9Sstevel@tonic-gate int32_t led_count; 12557c478bd9Sstevel@tonic-gate char led_state[32]; 12567c478bd9Sstevel@tonic-gate char *led_id; 12577c478bd9Sstevel@tonic-gate char *slot_id; 12587c478bd9Sstevel@tonic-gate char label[32]; 12597c478bd9Sstevel@tonic-gate char state[32], fault[32]; 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate threshold_counter = 0; 12627c478bd9Sstevel@tonic-gate strlcpy(fault, PSVC_GEN_FAULT, 12637c478bd9Sstevel@tonic-gate sizeof (fault)); 12647c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, fan_id[r], 12657c478bd9Sstevel@tonic-gate PSVC_FAULTID_ATTR, fault); 12667c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 12677c478bd9Sstevel@tonic-gate return (status); 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate strlcpy(state, PSVC_ERROR, 12707c478bd9Sstevel@tonic-gate sizeof (state)); 12717c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, fan_id[r], 12727c478bd9Sstevel@tonic-gate PSVC_STATE_ATTR, state); 12737c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 12747c478bd9Sstevel@tonic-gate return (status); 12757c478bd9Sstevel@tonic-gate 12767c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fan_id[r], 12777c478bd9Sstevel@tonic-gate PSVC_LABEL_ATTR, label); 12787c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 12797c478bd9Sstevel@tonic-gate return (status); 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_FAILURE_MSG, 12827c478bd9Sstevel@tonic-gate label); 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate /* turn on fault LEDs */ 12857c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, fan_id[r], 12867c478bd9Sstevel@tonic-gate PSVC_ASSOC_MATCHES_ATTR, &led_count, 12877c478bd9Sstevel@tonic-gate PSVC_DEV_FAULT_LED); 12887c478bd9Sstevel@tonic-gate strlcpy(led_state, PSVC_LED_ON, 12897c478bd9Sstevel@tonic-gate sizeof (led_state)); 12907c478bd9Sstevel@tonic-gate for (i = 0; i < led_count; ++i) { 12917c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, 12927c478bd9Sstevel@tonic-gate fan_id[r], 12937c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &led_id, 12947c478bd9Sstevel@tonic-gate PSVC_DEV_FAULT_LED, i); 12957c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 12967c478bd9Sstevel@tonic-gate return (status); 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, 12997c478bd9Sstevel@tonic-gate led_id, PSVC_LED_STATE_ATTR, 13007c478bd9Sstevel@tonic-gate led_state); 13017c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 13027c478bd9Sstevel@tonic-gate return (status); 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate /* turn on OK to remove LEDs */ 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fan_id[r], 13087c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &slot_id, 13097c478bd9Sstevel@tonic-gate PSVC_PARENT, 0); 13107c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13117c478bd9Sstevel@tonic-gate return (status); 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, slot_id, 13147c478bd9Sstevel@tonic-gate PSVC_ASSOC_MATCHES_ATTR, &led_count, 13157c478bd9Sstevel@tonic-gate PSVC_SLOT_REMOVE_LED); 13167c478bd9Sstevel@tonic-gate strlcpy(led_state, PSVC_LED_ON, 13177c478bd9Sstevel@tonic-gate sizeof (led_state)); 13187c478bd9Sstevel@tonic-gate for (i = 0; i < led_count; ++i) { 13197c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, 13207c478bd9Sstevel@tonic-gate slot_id, 13217c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &led_id, 13227c478bd9Sstevel@tonic-gate PSVC_SLOT_REMOVE_LED, i); 13237c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 13247c478bd9Sstevel@tonic-gate return (status); 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, 13277c478bd9Sstevel@tonic-gate led_id, PSVC_LED_STATE_ATTR, 13287c478bd9Sstevel@tonic-gate led_state); 13297c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 13307c478bd9Sstevel@tonic-gate return (status); 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate } 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 13387c478bd9Sstevel@tonic-gate } 13397c478bd9Sstevel@tonic-gate 13407c478bd9Sstevel@tonic-gate /* 13417c478bd9Sstevel@tonic-gate * This routine takes in the PSVC handle pointer, the PS name, and the 13427c478bd9Sstevel@tonic-gate * instance number (0, 1, or 2). It simply make a psvc_get call to get the 13437c478bd9Sstevel@tonic-gate * presence of each of the children under the PS. This call will set the 13447c478bd9Sstevel@tonic-gate * presence state of the child device if it was not there when the system 13457c478bd9Sstevel@tonic-gate * was booted. 13467c478bd9Sstevel@tonic-gate */ 13477c478bd9Sstevel@tonic-gate static int 13487c478bd9Sstevel@tonic-gate handle_ps_hotplug_children_presence(psvc_opaque_t hdlp, char *id) 13497c478bd9Sstevel@tonic-gate { 13507c478bd9Sstevel@tonic-gate char *sensor_id; 13517c478bd9Sstevel@tonic-gate char fail_valid_switch_id[PICL_PROPNAMELEN_MAX]; 13527c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 13537c478bd9Sstevel@tonic-gate boolean_t presence; 13547c478bd9Sstevel@tonic-gate int j; 13557c478bd9Sstevel@tonic-gate 13567c478bd9Sstevel@tonic-gate /* Get the Sensor Valid Switch presence */ 13577c478bd9Sstevel@tonic-gate snprintf(fail_valid_switch_id, sizeof (fail_valid_switch_id), "%s%s", 13587c478bd9Sstevel@tonic-gate id, "_SENSOR_VALID_SWITCH"); 13597c478bd9Sstevel@tonic-gate 13607c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fail_valid_switch_id, PSVC_PRESENCE_ATTR, 13617c478bd9Sstevel@tonic-gate &presence); 13627c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13637c478bd9Sstevel@tonic-gate return (status); 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate /* Go through each PS's fault sensors */ 13667c478bd9Sstevel@tonic-gate for (j = 0; j < DAK_MAX_FAULT_SENSORS; j++) { 13677c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 13687c478bd9Sstevel@tonic-gate &(sensor_id), PSVC_DEV_FAULT_SENSOR, j); 13697c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13707c478bd9Sstevel@tonic-gate return (status); 13717c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR, 13727c478bd9Sstevel@tonic-gate &presence); 13737c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13747c478bd9Sstevel@tonic-gate return (status); 13757c478bd9Sstevel@tonic-gate } 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate /* Go through each PS's current sensors */ 13787c478bd9Sstevel@tonic-gate for (j = 0; j < DAK_MAX_PS_I_SENSORS; ++j) { 13797c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 13807c478bd9Sstevel@tonic-gate &(sensor_id), PSVC_PS_I_SENSOR, j); 13817c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13827c478bd9Sstevel@tonic-gate return (status); 13837c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR, 13847c478bd9Sstevel@tonic-gate &presence); 13857c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13867c478bd9Sstevel@tonic-gate return (status); 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate } 13897c478bd9Sstevel@tonic-gate 13907c478bd9Sstevel@tonic-gate /* Go through each PS's onboard i2c hardware */ 13917c478bd9Sstevel@tonic-gate for (j = 0; j < 3; j++) { 13927c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 13937c478bd9Sstevel@tonic-gate &(sensor_id), PSVC_PHYSICAL_DEVICE, j); 13947c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13957c478bd9Sstevel@tonic-gate return (status); 13967c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, sensor_id, PSVC_PRESENCE_ATTR, 13977c478bd9Sstevel@tonic-gate &presence); 13987c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 13997c478bd9Sstevel@tonic-gate return (status); 14007c478bd9Sstevel@tonic-gate } 14017c478bd9Sstevel@tonic-gate 14027c478bd9Sstevel@tonic-gate return (status); 14037c478bd9Sstevel@tonic-gate } 14047c478bd9Sstevel@tonic-gate 14057c478bd9Sstevel@tonic-gate static i2c_hp_t devices[3][3] = { 14067c478bd9Sstevel@tonic-gate {{{0, 0x90}, "adio", "i2c-pcf8591"}, {{0, 0x70}, "ioexp", "i2c-pcf8574"}, 14077c478bd9Sstevel@tonic-gate {{0, 0xa0}, "fru", "i2c-at24c64"}}, 14087c478bd9Sstevel@tonic-gate {{{0, 0x92}, "adio", "i2c-pcf8591"}, {{0, 0x72}, "ioexp", "i2c-pcf8574"}, 14097c478bd9Sstevel@tonic-gate {{0, 0xa2}, "fru", "i2c-at24c64"}}, 14107c478bd9Sstevel@tonic-gate {{{0, 0x94}, "adio", "i2c-pcf8591"}, {{0, 0x74}, "ioexp", "i2c-pcf8574"}, 14117c478bd9Sstevel@tonic-gate {{0, 0xa4}, "fru", "i2c-at24c64"}}, 14127c478bd9Sstevel@tonic-gate }; 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate int32_t 14157c478bd9Sstevel@tonic-gate psvc_ps_hotplug_policy_0(psvc_opaque_t hdlp, char *id) 14167c478bd9Sstevel@tonic-gate { 14177c478bd9Sstevel@tonic-gate boolean_t presence, previous_presence; 14187c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 14197c478bd9Sstevel@tonic-gate char label[32], state[32], fault[32]; 14207c478bd9Sstevel@tonic-gate int32_t ps_instance, led_count; 14217c478bd9Sstevel@tonic-gate char *switch_id, *led_id; 14227c478bd9Sstevel@tonic-gate int i; 14237c478bd9Sstevel@tonic-gate picl_nodehdl_t parent_node; 14247c478bd9Sstevel@tonic-gate char parent_path[256], ps_path[256]; 14257c478bd9Sstevel@tonic-gate picl_nodehdl_t child_node; 14267c478bd9Sstevel@tonic-gate devctl_hdl_t bus_handle, dev_handle; 14277c478bd9Sstevel@tonic-gate devctl_ddef_t ddef_hdl; 14287c478bd9Sstevel@tonic-gate char pcf8574_devpath[256], pcf8591_devpath[256], fru_devpath[256]; 1429298b7f4cSjfrank int retry; 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, 1432*5eb92cf2Sdhain &previous_presence); 14337c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 14347c478bd9Sstevel@tonic-gate return (status); 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate retry = 0; 14377c478bd9Sstevel@tonic-gate do { 14387c478bd9Sstevel@tonic-gate if (retry) 1439298b7f4cSjfrank (void) sleep(retry_sleep_pshp); 14407c478bd9Sstevel@tonic-gate 14417c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 14427c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 14437c478bd9Sstevel@tonic-gate return (status); 14447c478bd9Sstevel@tonic-gate retry++; 1445298b7f4cSjfrank } while ((retry < n_retry_pshp) && 14467c478bd9Sstevel@tonic-gate (presence != previous_presence)); 14477c478bd9Sstevel@tonic-gate 14487c478bd9Sstevel@tonic-gate if (presence == previous_presence) { 14497c478bd9Sstevel@tonic-gate /* No change */ 14507c478bd9Sstevel@tonic-gate return (status); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 14547c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 14557c478bd9Sstevel@tonic-gate return (status); 14567c478bd9Sstevel@tonic-gate 14577c478bd9Sstevel@tonic-gate /* convert name to node, and parent path */ 14587c478bd9Sstevel@tonic-gate psvcplugin_lookup(id, parent_path, &child_node); 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate if (presence == PSVC_PRESENT) { 14617c478bd9Sstevel@tonic-gate /* 14627c478bd9Sstevel@tonic-gate * Run this code if Power Supply was just added into the 14637c478bd9Sstevel@tonic-gate * System. This code toggles hotplug switch and adds the 14647c478bd9Sstevel@tonic-gate * PS and it's children to the picl tree. We then goto adding 14657c478bd9Sstevel@tonic-gate * device drivers at bottom of the routine. 14667c478bd9Sstevel@tonic-gate */ 14677c478bd9Sstevel@tonic-gate int32_t switch_count; 14687c478bd9Sstevel@tonic-gate char state[32], fault[32]; 14697c478bd9Sstevel@tonic-gate char switch_state[32]; 14707c478bd9Sstevel@tonic-gate 14717c478bd9Sstevel@tonic-gate /* may detect presence before all connections are made */ 14727c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, 500); 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate /* Device added */ 14757c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_INSERTED_MSG, label); 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 14787c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 14797c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 14807c478bd9Sstevel@tonic-gate return (status); 14817c478bd9Sstevel@tonic-gate 14827c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 14837c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 14847c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 14857c478bd9Sstevel@tonic-gate return (status); 14867c478bd9Sstevel@tonic-gate 14877c478bd9Sstevel@tonic-gate /* Enable i2c bus */ 14887c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 1489*5eb92cf2Sdhain &switch_count, PSVC_HOTPLUG_ENABLE_SWITCH); 14907c478bd9Sstevel@tonic-gate for (i = 0; i < switch_count; ++i) { 14917c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1492*5eb92cf2Sdhain &switch_id, PSVC_HOTPLUG_ENABLE_SWITCH, i); 14937c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 14947c478bd9Sstevel@tonic-gate return (status); 14957c478bd9Sstevel@tonic-gate 14967c478bd9Sstevel@tonic-gate strcpy(switch_state, PSVC_SWITCH_OFF); 14977c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, switch_id, 1498*5eb92cf2Sdhain PSVC_SWITCH_STATE_ATTR, switch_state); 14997c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 15007c478bd9Sstevel@tonic-gate return (status); 15017c478bd9Sstevel@tonic-gate 15027c478bd9Sstevel@tonic-gate strcpy(switch_state, PSVC_SWITCH_ON); 15037c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, switch_id, 1504*5eb92cf2Sdhain PSVC_SWITCH_STATE_ATTR, switch_state); 15057c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) 15067c478bd9Sstevel@tonic-gate return (status); 15077c478bd9Sstevel@tonic-gate } 15087c478bd9Sstevel@tonic-gate ptree_get_node_by_path(parent_path, &parent_node); 15097c478bd9Sstevel@tonic-gate ptree_add_node(parent_node, child_node); 15107c478bd9Sstevel@tonic-gate snprintf(ps_path, sizeof (ps_path), "%s/%s", parent_path, id); 15117c478bd9Sstevel@tonic-gate psvcplugin_add_children(ps_path); 15127c478bd9Sstevel@tonic-gate } else { 15137c478bd9Sstevel@tonic-gate /* 15147c478bd9Sstevel@tonic-gate * Run this code if PS was just removed from the system. We 15157c478bd9Sstevel@tonic-gate * delete the device from the picl tree and then shut off 15167c478bd9Sstevel@tonic-gate * all fault lights associated with the PS. We also set the 15177c478bd9Sstevel@tonic-gate * device state to PSVC_REMOVED so that if we hit overcurrent 15187c478bd9Sstevel@tonic-gate * or fault checking code we can do a psvc call to see that 15197c478bd9Sstevel@tonic-gate * the device has not offically been added into the system. 15207c478bd9Sstevel@tonic-gate * We then will drop to code lower in the routine to remove 15217c478bd9Sstevel@tonic-gate * the device drivers for this PS. 15227c478bd9Sstevel@tonic-gate */ 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate /* Device removed */ 15257c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_REMOVED_MSG, label); 15267c478bd9Sstevel@tonic-gate ptree_delete_node(child_node); 15277c478bd9Sstevel@tonic-gate psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &led_count, 1528*5eb92cf2Sdhain PSVC_DEV_FAULT_LED); 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate for (i = 0; i < led_count; i++) { 15317c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1532*5eb92cf2Sdhain &led_id, PSVC_DEV_FAULT_LED, i); 15337c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 15347c478bd9Sstevel@tonic-gate return (status); 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate 15377c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, led_id, 15387c478bd9Sstevel@tonic-gate PSVC_LED_STATE_ATTR, PSVC_OFF); 15397c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 15407c478bd9Sstevel@tonic-gate syslog(LOG_ERR, SET_LED_FAILED_MSG, led_id, 1541*5eb92cf2Sdhain errno); 15427c478bd9Sstevel@tonic-gate return (status); 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate } 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate strcpy(state, PSVC_OK); 15487c478bd9Sstevel@tonic-gate strcpy(fault, PSVC_NO_FAULT); 15497c478bd9Sstevel@tonic-gate 15507c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 15517c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 15527c478bd9Sstevel@tonic-gate return (status); 15537c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 15547c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 15557c478bd9Sstevel@tonic-gate return (status); 15567c478bd9Sstevel@tonic-gate } 15577c478bd9Sstevel@tonic-gate 15587c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence); 15597c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 15607c478bd9Sstevel@tonic-gate return (status); 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_INSTANCE_ATTR, &ps_instance); 15637c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 15647c478bd9Sstevel@tonic-gate return (status); 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate if (presence != PSVC_PRESENT) { 15677c478bd9Sstevel@tonic-gate /* 15687c478bd9Sstevel@tonic-gate * This is the additional code needed to remove the PS from 15697c478bd9Sstevel@tonic-gate * the system. It removes the device drivers from the 15707c478bd9Sstevel@tonic-gate * device tree. 15717c478bd9Sstevel@tonic-gate */ 15727c478bd9Sstevel@tonic-gate snprintf(pcf8574_devpath, sizeof (pcf8574_devpath), PCF8574, 1573*5eb92cf2Sdhain devices[ps_instance][1].addr[1]); 15747c478bd9Sstevel@tonic-gate snprintf(pcf8591_devpath, sizeof (pcf8591_devpath), PCF8591, 1575*5eb92cf2Sdhain devices[ps_instance][0].addr[1]); 15767c478bd9Sstevel@tonic-gate snprintf(fru_devpath, sizeof (fru_devpath), FRU, 1577*5eb92cf2Sdhain devices[ps_instance][2].addr[1]); 15787c478bd9Sstevel@tonic-gate 15797c478bd9Sstevel@tonic-gate dev_handle = devctl_device_acquire(pcf8591_devpath, 0); 15807c478bd9Sstevel@tonic-gate if (dev_handle == NULL) { 15817c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1582*5eb92cf2Sdhain pcf8591_devpath, errno); 15837c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 15847c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 15857c478bd9Sstevel@tonic-gate } else if ((devctl_device_remove(dev_handle)) && 1586*5eb92cf2Sdhain (errno != ENXIO)) { 15877c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, 1588*5eb92cf2Sdhain pcf8591_devpath, errno); 15897c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 15907c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 15917c478bd9Sstevel@tonic-gate } else { 15927c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 15937c478bd9Sstevel@tonic-gate status = PSVC_SUCCESS; 15947c478bd9Sstevel@tonic-gate } 15957c478bd9Sstevel@tonic-gate 15967c478bd9Sstevel@tonic-gate dev_handle = devctl_device_acquire(pcf8574_devpath, 0); 15977c478bd9Sstevel@tonic-gate if (dev_handle == NULL) { 15987c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1599*5eb92cf2Sdhain pcf8574_devpath, errno); 16007c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 16017c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16027c478bd9Sstevel@tonic-gate } else if ((devctl_device_remove(dev_handle)) && 1603*5eb92cf2Sdhain (errno != ENXIO)) { 16047c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, 1605*5eb92cf2Sdhain pcf8574_devpath, errno); 16067c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 16077c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16087c478bd9Sstevel@tonic-gate } else { 16097c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 16107c478bd9Sstevel@tonic-gate status = PSVC_SUCCESS; 16117c478bd9Sstevel@tonic-gate } 16127c478bd9Sstevel@tonic-gate 16137c478bd9Sstevel@tonic-gate dev_handle = devctl_device_acquire(fru_devpath, 0); 16147c478bd9Sstevel@tonic-gate if (dev_handle == NULL) { 16157c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1616*5eb92cf2Sdhain fru_devpath, errno); 16177c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 16187c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16197c478bd9Sstevel@tonic-gate } else if ((devctl_device_remove(dev_handle)) && 1620*5eb92cf2Sdhain (errno != ENXIO)) { 16217c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_DELETE_FAILED, 1622*5eb92cf2Sdhain fru_devpath, errno); 16237c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 16247c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16257c478bd9Sstevel@tonic-gate } else { 16267c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 16277c478bd9Sstevel@tonic-gate status = PSVC_SUCCESS; 16287c478bd9Sstevel@tonic-gate } 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate return (status); 16317c478bd9Sstevel@tonic-gate } 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate /* 16347c478bd9Sstevel@tonic-gate * This code is to update the presences of power supply child 16357c478bd9Sstevel@tonic-gate * devices in the event that picld was started without a power 16367c478bd9Sstevel@tonic-gate * supply present. This call makes the devices available 16377c478bd9Sstevel@tonic-gate * after that initial insertion. 16387c478bd9Sstevel@tonic-gate */ 16397c478bd9Sstevel@tonic-gate status = handle_ps_hotplug_children_presence(hdlp, id); 16407c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 16417c478bd9Sstevel@tonic-gate return (status); 16427c478bd9Sstevel@tonic-gate } 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate /* 16457c478bd9Sstevel@tonic-gate * We fall through to here if the device has been inserted. 16467c478bd9Sstevel@tonic-gate * Add the devinfo tree node entry for the seeprom and attach 16477c478bd9Sstevel@tonic-gate * the i2c seeprom driver 16487c478bd9Sstevel@tonic-gate */ 16497c478bd9Sstevel@tonic-gate 16507c478bd9Sstevel@tonic-gate bus_handle = devctl_bus_acquire(I2C_NODE, 0); 16517c478bd9Sstevel@tonic-gate if (bus_handle == NULL) { 16527c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, I2C_NODE, errno); 16537c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate /* Create the deivce nodes for all 3 i2c parts on the PS */ 16567c478bd9Sstevel@tonic-gate for (i = 0; i < 3; i++) { 16577c478bd9Sstevel@tonic-gate ddef_hdl = devctl_ddef_alloc(devices[ps_instance][i].name, 0); 16587c478bd9Sstevel@tonic-gate if (ddef_hdl == NULL) { 16597c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1660*5eb92cf2Sdhain devices[ps_instance][i].name, errno); 16617c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16627c478bd9Sstevel@tonic-gate } 16637c478bd9Sstevel@tonic-gate status = devctl_ddef_string(ddef_hdl, "compatible", 1664*5eb92cf2Sdhain devices[ps_instance][i].compatible); 16657c478bd9Sstevel@tonic-gate if (status == -1) { 16667c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1667*5eb92cf2Sdhain devices[ps_instance][i].name, errno); 16687c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16697c478bd9Sstevel@tonic-gate } 16707c478bd9Sstevel@tonic-gate status = devctl_ddef_int_array(ddef_hdl, "reg", 2, 1671*5eb92cf2Sdhain devices[ps_instance][i].addr); 16727c478bd9Sstevel@tonic-gate if (status == -1) { 16737c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVICE_HANDLE_FAIL_MSG, 1674*5eb92cf2Sdhain devices[ps_instance][i].name, errno); 16757c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate if (devctl_bus_dev_create(bus_handle, ddef_hdl, 0, 1678*5eb92cf2Sdhain &dev_handle)) { 16797c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DEVTREE_NODE_CREATE_FAILED, 1680*5eb92cf2Sdhain devices[ps_instance][i].name, errno); 16817c478bd9Sstevel@tonic-gate return (PSVC_FAILURE); 16827c478bd9Sstevel@tonic-gate } else 16837c478bd9Sstevel@tonic-gate devctl_release(dev_handle); 16847c478bd9Sstevel@tonic-gate devctl_ddef_free(ddef_hdl); 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate devctl_release(bus_handle); 16877c478bd9Sstevel@tonic-gate 16887c478bd9Sstevel@tonic-gate return (status); 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate static void 16927c478bd9Sstevel@tonic-gate shutdown_routine() 16937c478bd9Sstevel@tonic-gate { 16947c478bd9Sstevel@tonic-gate static boolean_t shutdown_flag = 0; 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate if (!(shutdown_flag)) { 16977c478bd9Sstevel@tonic-gate system(shutdown_string); 16987c478bd9Sstevel@tonic-gate shutdown_flag = 1; 16997c478bd9Sstevel@tonic-gate } 17007c478bd9Sstevel@tonic-gate } 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate /* 17037c478bd9Sstevel@tonic-gate * This policy checks temperature sensors to see if the fault attribute 17047c478bd9Sstevel@tonic-gate * is set to either High or Low Shutdown. If so then it shuts the system 17057c478bd9Sstevel@tonic-gate * down with a 1 minute warning period 17067c478bd9Sstevel@tonic-gate */ 17077c478bd9Sstevel@tonic-gate int32_t 17087c478bd9Sstevel@tonic-gate psvc_shutdown_policy(psvc_opaque_t hdlp, char *id) 17097c478bd9Sstevel@tonic-gate { 17107c478bd9Sstevel@tonic-gate int32_t status; 17117c478bd9Sstevel@tonic-gate char fault[32] = {0}; 17127c478bd9Sstevel@tonic-gate boolean_t pr; 1713298b7f4cSjfrank int retry; 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &pr); 17167c478bd9Sstevel@tonic-gate if ((status != PSVC_SUCCESS) || (pr != PSVC_PRESENT)) { 17177c478bd9Sstevel@tonic-gate return (status); 17187c478bd9Sstevel@tonic-gate } 17197c478bd9Sstevel@tonic-gate 1720298b7f4cSjfrank retry = 0; 1721298b7f4cSjfrank do { 1722298b7f4cSjfrank if (retry) 1723298b7f4cSjfrank (void) sleep(retry_sleep_temp_shutdown); 1724298b7f4cSjfrank status = psvc_get_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 1725298b7f4cSjfrank if (status != PSVC_SUCCESS) 1726298b7f4cSjfrank return (status); 1727298b7f4cSjfrank retry++; 1728298b7f4cSjfrank } while (((strcmp(fault, PSVC_TEMP_LO_SHUT) == 0) || 1729298b7f4cSjfrank (strcmp(fault, PSVC_TEMP_HI_SHUT) == 0)) && 1730*5eb92cf2Sdhain (retry < n_retry_temp_shutdown)); 17317c478bd9Sstevel@tonic-gate if ((strcmp(fault, PSVC_TEMP_LO_SHUT) == 0) || 17327c478bd9Sstevel@tonic-gate (strcmp(fault, PSVC_TEMP_HI_SHUT) == 0)) { 17337c478bd9Sstevel@tonic-gate shutdown_routine(); 17347c478bd9Sstevel@tonic-gate } 17357c478bd9Sstevel@tonic-gate 17367c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 17377c478bd9Sstevel@tonic-gate } 17387c478bd9Sstevel@tonic-gate 17397c478bd9Sstevel@tonic-gate int32_t 17407c478bd9Sstevel@tonic-gate psvc_check_disk_fault_policy_0(psvc_opaque_t hdlp, char *id) 17417c478bd9Sstevel@tonic-gate { 17427c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 17437c478bd9Sstevel@tonic-gate int32_t i; 17447c478bd9Sstevel@tonic-gate char curr_state[32], prev_state[32], led_state[32]; 17457c478bd9Sstevel@tonic-gate char disk_fault[32], disk_state[32]; 1746360e6f5eSmathue static char *disk_id[DAK_MAX_DISKS] = {NULL}; 1747360e6f5eSmathue static char *led_id[DAK_MAX_DISKS] = {NULL}; 1748360e6f5eSmathue static char *parent_id[DAK_MAX_DISKS] = {NULL}; 17497c478bd9Sstevel@tonic-gate boolean_t present; 1750298b7f4cSjfrank int retry; 17517c478bd9Sstevel@tonic-gate 17527c478bd9Sstevel@tonic-gate /* 17537c478bd9Sstevel@tonic-gate * Check which disk faulted, now get the disks. 17547c478bd9Sstevel@tonic-gate * We are now going to get disk, disk parent, 17557c478bd9Sstevel@tonic-gate * parent's leds, and check to see if parent's leds are on 17567c478bd9Sstevel@tonic-gate */ 17577c478bd9Sstevel@tonic-gate 17587c478bd9Sstevel@tonic-gate if (disk_id[0] == NULL) { 17597c478bd9Sstevel@tonic-gate for (i = 0; i < DAK_MAX_DISKS; i++) { 17607c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 17617c478bd9Sstevel@tonic-gate &(disk_id[i]), PSVC_DISK, i); 17627c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 17637c478bd9Sstevel@tonic-gate return (status); 17647c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, disk_id[i], 17657c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &(parent_id[i]), 17667c478bd9Sstevel@tonic-gate PSVC_PARENT, 0); 17677c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 17687c478bd9Sstevel@tonic-gate return (status); 17697c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, parent_id[i], 17707c478bd9Sstevel@tonic-gate PSVC_ASSOC_ID_ATTR, &(led_id[i]), 17717c478bd9Sstevel@tonic-gate PSVC_SLOT_FAULT_LED, 0); 17727c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 17737c478bd9Sstevel@tonic-gate return (status); 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate } 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate for (i = 0; i < DAK_MAX_DISKS; i++) { 17797c478bd9Sstevel@tonic-gate curr_state[0] = 0; 17807c478bd9Sstevel@tonic-gate prev_state[0] = 0; 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, disk_id[i], PSVC_PRESENCE_ATTR, 1783*5eb92cf2Sdhain &present); 17847c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 17857c478bd9Sstevel@tonic-gate return (status); 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate if (present == PSVC_ABSENT) 17887c478bd9Sstevel@tonic-gate continue; 17897c478bd9Sstevel@tonic-gate 17907c478bd9Sstevel@tonic-gate /* 17917c478bd9Sstevel@tonic-gate * Check if whether or not the led is on. 17927c478bd9Sstevel@tonic-gate * If so, then this disk has a problem and 17937c478bd9Sstevel@tonic-gate * set its fault and error states to bad. 17947c478bd9Sstevel@tonic-gate * If not, then set fault and error states to good. 17957c478bd9Sstevel@tonic-gate * If the disk underwent a change in state, then 17967c478bd9Sstevel@tonic-gate * print out what state it's now in. 17977c478bd9Sstevel@tonic-gate */ 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, disk_id[i], PSVC_STATE_ATTR, 18007c478bd9Sstevel@tonic-gate prev_state); 18017c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18027c478bd9Sstevel@tonic-gate return (status); 18037c478bd9Sstevel@tonic-gate 18047c478bd9Sstevel@tonic-gate retry = 0; 18057c478bd9Sstevel@tonic-gate do { 18067c478bd9Sstevel@tonic-gate if (retry) 1807298b7f4cSjfrank (void) sleep(retry_sleep_diskfault); 18087c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, led_id[i], PSVC_STATE_ATTR, 18097c478bd9Sstevel@tonic-gate led_state); 18107c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18117c478bd9Sstevel@tonic-gate return (status); 18127c478bd9Sstevel@tonic-gate retry++; 18137c478bd9Sstevel@tonic-gate /* 18147c478bd9Sstevel@tonic-gate * check to see if we need to retry. the conditions are: 18157c478bd9Sstevel@tonic-gate * 18167c478bd9Sstevel@tonic-gate * prev_state led_state retry 18177c478bd9Sstevel@tonic-gate * -------------------------------------------------- 18187c478bd9Sstevel@tonic-gate * PSVC_ERROR PSVC_LED_ON yes 18197c478bd9Sstevel@tonic-gate * PSVC_OK PSVC_LED_OFF yes 18207c478bd9Sstevel@tonic-gate * PSVC_ERROR PSVC_LED_OFF no 18217c478bd9Sstevel@tonic-gate * PSVC_OK PSVC_LED_ON no 18227c478bd9Sstevel@tonic-gate */ 1823298b7f4cSjfrank } while ((retry < n_retry_diskfault) && 18247c478bd9Sstevel@tonic-gate change_of_state_str(prev_state, PSVC_OK, 18257c478bd9Sstevel@tonic-gate led_state, PSVC_LED_ON)); 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate /* 18287c478bd9Sstevel@tonic-gate * Set the disk's state and fault id according to 18297c478bd9Sstevel@tonic-gate * what we found the disk fault sensor (disk_slot_fault_led) 18307c478bd9Sstevel@tonic-gate * to be. 18317c478bd9Sstevel@tonic-gate */ 18327c478bd9Sstevel@tonic-gate if (strcmp(led_state, PSVC_LED_ON) == 0) { 18337c478bd9Sstevel@tonic-gate strcpy(disk_fault, PSVC_GEN_FAULT); 18347c478bd9Sstevel@tonic-gate strcpy(disk_state, PSVC_ERROR); 18357c478bd9Sstevel@tonic-gate } else { 18367c478bd9Sstevel@tonic-gate strcpy(disk_fault, PSVC_NO_FAULT); 18377c478bd9Sstevel@tonic-gate strcpy(disk_state, PSVC_OK); 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, disk_id[i], PSVC_STATE_ATTR, 1840*5eb92cf2Sdhain disk_state); 18417c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18427c478bd9Sstevel@tonic-gate return (status); 18437c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, disk_id[i], PSVC_FAULTID_ATTR, 1844*5eb92cf2Sdhain disk_fault); 18457c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18467c478bd9Sstevel@tonic-gate return (status); 18477c478bd9Sstevel@tonic-gate /* 18487c478bd9Sstevel@tonic-gate * Check disk states. If they differ, then print out 18497c478bd9Sstevel@tonic-gate * the current state of the disk 18507c478bd9Sstevel@tonic-gate */ 18517c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, disk_id[i], PSVC_PREV_STATE_ATTR, 1852*5eb92cf2Sdhain prev_state); 18537c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18547c478bd9Sstevel@tonic-gate return (status); 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate if (strcmp(disk_state, prev_state) != 0) { 18577c478bd9Sstevel@tonic-gate if (strcmp(disk_state, PSVC_ERROR) == 0) { 18587c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DISK_FAULT_MSG, disk_id[i]); 18597c478bd9Sstevel@tonic-gate } else { 18607c478bd9Sstevel@tonic-gate syslog(LOG_ERR, DISK_OK_MSG, disk_id[i]); 18617c478bd9Sstevel@tonic-gate } 18627c478bd9Sstevel@tonic-gate } 18637c478bd9Sstevel@tonic-gate } 18647c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 18657c478bd9Sstevel@tonic-gate } 18667c478bd9Sstevel@tonic-gate 18677c478bd9Sstevel@tonic-gate int32_t 18687c478bd9Sstevel@tonic-gate psvc_update_FSP_fault_led_policy_0(psvc_opaque_t hdlp, char *id) 18697c478bd9Sstevel@tonic-gate { 18707c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 18717c478bd9Sstevel@tonic-gate int32_t i; 18727c478bd9Sstevel@tonic-gate int32_t dev_count, fault_state = 0; 18737c478bd9Sstevel@tonic-gate char *dev_id; 18747c478bd9Sstevel@tonic-gate char dev_state[32], led_state[32]; 18757c478bd9Sstevel@tonic-gate boolean_t present; 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &dev_count, 1878*5eb92cf2Sdhain PSVC_DEV_FAULT_SENSOR); 18797c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18807c478bd9Sstevel@tonic-gate return (status); 18817c478bd9Sstevel@tonic-gate 18827c478bd9Sstevel@tonic-gate fault_state = 0; 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate for (i = 0; i < dev_count; i++) { 18857c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1886*5eb92cf2Sdhain &dev_id, PSVC_DEV_FAULT_SENSOR, i); 18877c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18887c478bd9Sstevel@tonic-gate return (status); 18897c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, dev_id, PSVC_PRESENCE_ATTR, 1890*5eb92cf2Sdhain &present); 18917c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 18927c478bd9Sstevel@tonic-gate return (status); 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate if (present == PSVC_ABSENT) 18957c478bd9Sstevel@tonic-gate continue; 18967c478bd9Sstevel@tonic-gate 18977c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, dev_id, PSVC_STATE_ATTR, 1898*5eb92cf2Sdhain dev_state); 18997c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19007c478bd9Sstevel@tonic-gate return (status); 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate if (strcmp(dev_state, PSVC_ERROR) == 0) { 19037c478bd9Sstevel@tonic-gate fault_state = 1; 19047c478bd9Sstevel@tonic-gate } 19057c478bd9Sstevel@tonic-gate } 19067c478bd9Sstevel@tonic-gate if (fault_state == 1) { 19077c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 19087c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19097c478bd9Sstevel@tonic-gate return (status); 19107c478bd9Sstevel@tonic-gate if (strcmp(led_state, PSVC_OFF) == 0) { 19117c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 19127c478bd9Sstevel@tonic-gate PSVC_ON); 19137c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19147c478bd9Sstevel@tonic-gate return (status); 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate } else { 19177c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 19187c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19197c478bd9Sstevel@tonic-gate return (status); 19207c478bd9Sstevel@tonic-gate if (strcmp(led_state, PSVC_ON) == 0) { 19217c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 19227c478bd9Sstevel@tonic-gate PSVC_OFF); 19237c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19247c478bd9Sstevel@tonic-gate return (status); 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate status = update_gen_fault_led(hdlp, GEN_FAULT_LED); 19287c478bd9Sstevel@tonic-gate 19297c478bd9Sstevel@tonic-gate return (status); 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate int32_t 19337c478bd9Sstevel@tonic-gate update_gen_fault_led(psvc_opaque_t hdlp, char *id) 19347c478bd9Sstevel@tonic-gate { 19357c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 19367c478bd9Sstevel@tonic-gate int32_t i; 19377c478bd9Sstevel@tonic-gate int32_t led_count, fault_state; 19387c478bd9Sstevel@tonic-gate char *led_id; 19397c478bd9Sstevel@tonic-gate char led_state[32]; 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &led_count, 1942*5eb92cf2Sdhain PSVC_DEV_FAULT_SENSOR); 19437c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19447c478bd9Sstevel@tonic-gate return (status); 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate fault_state = 0; 19477c478bd9Sstevel@tonic-gate 19487c478bd9Sstevel@tonic-gate for (i = 0; i < led_count; i++) { 19497c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1950*5eb92cf2Sdhain &led_id, PSVC_DEV_FAULT_SENSOR, i); 19517c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19527c478bd9Sstevel@tonic-gate return (status); 19537c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, led_id, PSVC_STATE_ATTR, 1954*5eb92cf2Sdhain led_state); 19557c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19567c478bd9Sstevel@tonic-gate return (status); 19577c478bd9Sstevel@tonic-gate 19587c478bd9Sstevel@tonic-gate if (strcmp(led_state, PSVC_ON) == 0) { 19597c478bd9Sstevel@tonic-gate fault_state = 1; 19607c478bd9Sstevel@tonic-gate } 19617c478bd9Sstevel@tonic-gate } 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate if (fault_state == 1) { 19647c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 19657c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19667c478bd9Sstevel@tonic-gate return (status); 19677c478bd9Sstevel@tonic-gate if (strcmp(led_state, PSVC_OFF) == 0) { 19687c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 19697c478bd9Sstevel@tonic-gate PSVC_ON); 19707c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19717c478bd9Sstevel@tonic-gate return (status); 19727c478bd9Sstevel@tonic-gate } 19737c478bd9Sstevel@tonic-gate } else { 19747c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, led_state); 19757c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19767c478bd9Sstevel@tonic-gate return (status); 19777c478bd9Sstevel@tonic-gate if (strcmp(led_state, PSVC_ON) == 0) { 19787c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 19797c478bd9Sstevel@tonic-gate PSVC_OFF); 19807c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 19817c478bd9Sstevel@tonic-gate return (status); 19827c478bd9Sstevel@tonic-gate } 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate return (status); 19867c478bd9Sstevel@tonic-gate } 19877c478bd9Sstevel@tonic-gate 19887c478bd9Sstevel@tonic-gate 19897c478bd9Sstevel@tonic-gate /* 19907c478bd9Sstevel@tonic-gate * This function detects whether the module present in the dakatari's 19917c478bd9Sstevel@tonic-gate * CPU slot is a CPU module or a Zulu (XVR-4000). 19927c478bd9Sstevel@tonic-gate * Based on this detection it also sets the appropriate temperature sensors 19937c478bd9Sstevel@tonic-gate * to HOTPLUGGED, so that it works properly with check_temp() function 19947c478bd9Sstevel@tonic-gate */ 19957c478bd9Sstevel@tonic-gate #define MAX_MODULE_SIZE 20 19967c478bd9Sstevel@tonic-gate #define MAX_TEMP_SENSOR_SIZE 30 19977c478bd9Sstevel@tonic-gate 19987c478bd9Sstevel@tonic-gate int32_t 19997c478bd9Sstevel@tonic-gate psvc_update_cpu_module_card_node_0(psvc_opaque_t hdlp, char *id) 20007c478bd9Sstevel@tonic-gate { 20017c478bd9Sstevel@tonic-gate int32_t set_temp_sensor_properties(psvc_opaque_t, char *); 20027c478bd9Sstevel@tonic-gate int32_t remove_module_node(psvc_opaque_t, char *); 20037c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 20047c478bd9Sstevel@tonic-gate fru_info_t fru_data; 20057c478bd9Sstevel@tonic-gate char *fru, seg_name[2]; 20067c478bd9Sstevel@tonic-gate int8_t seg_count, module_card; 20077c478bd9Sstevel@tonic-gate int32_t match_count, i, j, seg_desc_start = 0x1806, module_address; 20087c478bd9Sstevel@tonic-gate int32_t seg_found; 20097c478bd9Sstevel@tonic-gate boolean_t present; 20107c478bd9Sstevel@tonic-gate seg_desc_t segment; 20117c478bd9Sstevel@tonic-gate char other_module_id[MAX_MODULE_SIZE]; 20127c478bd9Sstevel@tonic-gate char cpu_temp_sensor1[MAX_TEMP_SENSOR_SIZE]; 20137c478bd9Sstevel@tonic-gate char cpu_temp_sensor2[MAX_TEMP_SENSOR_SIZE]; 20147c478bd9Sstevel@tonic-gate char zulu_temp_sensor1[MAX_TEMP_SENSOR_SIZE]; 20157c478bd9Sstevel@tonic-gate char zulu_temp_sensor2[MAX_TEMP_SENSOR_SIZE]; 20167c478bd9Sstevel@tonic-gate int offset = 0x7; 20177c478bd9Sstevel@tonic-gate 20187c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 20197c478bd9Sstevel@tonic-gate if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) { 20207c478bd9Sstevel@tonic-gate return (status); 20217c478bd9Sstevel@tonic-gate } 20227c478bd9Sstevel@tonic-gate 20237c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count, 20247c478bd9Sstevel@tonic-gate PSVC_FRU); 20257c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 20267c478bd9Sstevel@tonic-gate return (status); 20277c478bd9Sstevel@tonic-gate } 20287c478bd9Sstevel@tonic-gate 20297c478bd9Sstevel@tonic-gate for (i = 0; i < match_count; i++) { 20307c478bd9Sstevel@tonic-gate seg_found = 0; 20317c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &fru, 20327c478bd9Sstevel@tonic-gate PSVC_FRU, i); 20337c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) 20347c478bd9Sstevel@tonic-gate return (status); 20357c478bd9Sstevel@tonic-gate 20367c478bd9Sstevel@tonic-gate fru_data.buf_start = 0x1805; 20377c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&seg_count; 20387c478bd9Sstevel@tonic-gate fru_data.read_size = 1; 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 20417c478bd9Sstevel@tonic-gate &fru_data); 20427c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 20437c478bd9Sstevel@tonic-gate return (status); 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate for (j = 0; (j < seg_count) && (!seg_found); j++) { 20477c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 20487c478bd9Sstevel@tonic-gate fru_data.buf = seg_name; 20497c478bd9Sstevel@tonic-gate fru_data.read_size = 2; 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 20527c478bd9Sstevel@tonic-gate &fru_data); 20537c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 20547c478bd9Sstevel@tonic-gate syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG); 20557c478bd9Sstevel@tonic-gate return (status); 20567c478bd9Sstevel@tonic-gate } 20577c478bd9Sstevel@tonic-gate 20587c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + 2; 20597c478bd9Sstevel@tonic-gate fru_data.buf_start = seg_desc_start; 20607c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&segment; 20617c478bd9Sstevel@tonic-gate fru_data.read_size = sizeof (seg_desc_t); 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 20647c478bd9Sstevel@tonic-gate &fru_data); 20657c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 20667c478bd9Sstevel@tonic-gate syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG); 20677c478bd9Sstevel@tonic-gate return (status); 20687c478bd9Sstevel@tonic-gate } 20697c478bd9Sstevel@tonic-gate seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 20707c478bd9Sstevel@tonic-gate if (memcmp(seg_name, "SC", 2) == 0) 20717c478bd9Sstevel@tonic-gate seg_found = 1; 20727c478bd9Sstevel@tonic-gate } 20737c478bd9Sstevel@tonic-gate 20747c478bd9Sstevel@tonic-gate if (seg_found) { 20757c478bd9Sstevel@tonic-gate module_address = segment.segoffset + offset; 20767c478bd9Sstevel@tonic-gate fru_data.buf_start = module_address; 20777c478bd9Sstevel@tonic-gate fru_data.buf = (char *)&module_card; 20787c478bd9Sstevel@tonic-gate fru_data.read_size = 1; 20797c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 20807c478bd9Sstevel@tonic-gate &fru_data); 20817c478bd9Sstevel@tonic-gate if (status != PSVC_SUCCESS) { 20827c478bd9Sstevel@tonic-gate syslog(LOG_ERR, GET_ATTR_FRU_FAILED_MSG); 20837c478bd9Sstevel@tonic-gate return (status); 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate } else { 20867c478bd9Sstevel@tonic-gate syslog(LOG_ERR, NO_FRU_INFO_MSG, id); 20877c478bd9Sstevel@tonic-gate } 20887c478bd9Sstevel@tonic-gate } 20897c478bd9Sstevel@tonic-gate 20907c478bd9Sstevel@tonic-gate if (strcmp(id, "ZULU_1_3_MOD_CARD") == 0) { 20917c478bd9Sstevel@tonic-gate strlcpy(other_module_id, "CPU_1_3_MOD_CARD", MAX_MODULE_SIZE); 20927c478bd9Sstevel@tonic-gate 20937c478bd9Sstevel@tonic-gate strlcpy(cpu_temp_sensor1, "CPU1_DIE_TEMPERATURE_SENSOR", 20947c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 20957c478bd9Sstevel@tonic-gate strlcpy(cpu_temp_sensor2, "CPU3_DIE_TEMPERATURE_SENSOR", 20967c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 20977c478bd9Sstevel@tonic-gate 20987c478bd9Sstevel@tonic-gate strlcpy(zulu_temp_sensor1, "ZULU1_DIE_TEMPERATURE_SENSOR", 20997c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 21007c478bd9Sstevel@tonic-gate strlcpy(zulu_temp_sensor2, "ZULU3_DIE_TEMPERATURE_SENSOR", 21017c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 21027c478bd9Sstevel@tonic-gate } 21037c478bd9Sstevel@tonic-gate 21047c478bd9Sstevel@tonic-gate if (strcmp(id, "ZULU_4_6_MOD_CARD") == 0) { 21057c478bd9Sstevel@tonic-gate strlcpy(other_module_id, "CPU_4_6_MOD_CARD", MAX_MODULE_SIZE); 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate strlcpy(cpu_temp_sensor1, "CPU4_DIE_TEMPERATURE_SENSOR", 21087c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 21097c478bd9Sstevel@tonic-gate strlcpy(cpu_temp_sensor2, "CPU6_DIE_TEMPERATURE_SENSOR", 21107c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 21117c478bd9Sstevel@tonic-gate 21127c478bd9Sstevel@tonic-gate strlcpy(zulu_temp_sensor1, "ZULU4_DIE_TEMPERATURE_SENSOR", 21137c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 21147c478bd9Sstevel@tonic-gate strlcpy(zulu_temp_sensor2, "ZULU6_DIE_TEMPERATURE_SENSOR", 21157c478bd9Sstevel@tonic-gate MAX_TEMP_SENSOR_SIZE); 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate 21197c478bd9Sstevel@tonic-gate /* 21207c478bd9Sstevel@tonic-gate * If the module in the CPU slot is a Zulu (XVR-4000), then 21217c478bd9Sstevel@tonic-gate * location 0x1EB0 in its FRUid prom has a value 0xFB. 21227c478bd9Sstevel@tonic-gate * If Zulu (XVR-4000) is detected, delete the CPU node, otherwise 21237c478bd9Sstevel@tonic-gate * delete the Zulu node. Also set the temperature sensor value to 21247c478bd9Sstevel@tonic-gate * HOTPLUGGED for absent temperature sensors. 21257c478bd9Sstevel@tonic-gate */ 21267c478bd9Sstevel@tonic-gate if ((module_card & 0xff) == 0xfb) { 21277c478bd9Sstevel@tonic-gate status = set_temp_sensor_properties(hdlp, cpu_temp_sensor1); 21287c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 21297c478bd9Sstevel@tonic-gate return (status); 21307c478bd9Sstevel@tonic-gate } 21317c478bd9Sstevel@tonic-gate 21327c478bd9Sstevel@tonic-gate status = set_temp_sensor_properties(hdlp, cpu_temp_sensor2); 21337c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 21347c478bd9Sstevel@tonic-gate return (status); 21357c478bd9Sstevel@tonic-gate } 21367c478bd9Sstevel@tonic-gate 21377c478bd9Sstevel@tonic-gate /* 21387c478bd9Sstevel@tonic-gate * Remove CPU node 21397c478bd9Sstevel@tonic-gate */ 21407c478bd9Sstevel@tonic-gate status = remove_module_node(hdlp, other_module_id); 21417c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 21427c478bd9Sstevel@tonic-gate return (status); 21437c478bd9Sstevel@tonic-gate } 21447c478bd9Sstevel@tonic-gate } else { 21457c478bd9Sstevel@tonic-gate status = set_temp_sensor_properties(hdlp, zulu_temp_sensor1); 21467c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 21477c478bd9Sstevel@tonic-gate return (status); 21487c478bd9Sstevel@tonic-gate } 21497c478bd9Sstevel@tonic-gate status = set_temp_sensor_properties(hdlp, zulu_temp_sensor2); 21507c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 21517c478bd9Sstevel@tonic-gate return (status); 21527c478bd9Sstevel@tonic-gate } 21537c478bd9Sstevel@tonic-gate 21547c478bd9Sstevel@tonic-gate /* 21557c478bd9Sstevel@tonic-gate * Remove Zulu (XVR-4000) node 21567c478bd9Sstevel@tonic-gate */ 21577c478bd9Sstevel@tonic-gate status = remove_module_node(hdlp, id); 21587c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 21597c478bd9Sstevel@tonic-gate return (status); 21607c478bd9Sstevel@tonic-gate } 21617c478bd9Sstevel@tonic-gate } 21627c478bd9Sstevel@tonic-gate 21637c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 21647c478bd9Sstevel@tonic-gate } 21657c478bd9Sstevel@tonic-gate 21667c478bd9Sstevel@tonic-gate 21677c478bd9Sstevel@tonic-gate /* 21687c478bd9Sstevel@tonic-gate * Remove the CPU slot's module node 21697c478bd9Sstevel@tonic-gate */ 21707c478bd9Sstevel@tonic-gate int32_t 21717c478bd9Sstevel@tonic-gate remove_module_node(psvc_opaque_t hdlp, char *id) 21727c478bd9Sstevel@tonic-gate { 21737c478bd9Sstevel@tonic-gate char parent_path[256]; 21747c478bd9Sstevel@tonic-gate picl_nodehdl_t child_node; 21757c478bd9Sstevel@tonic-gate 21767c478bd9Sstevel@tonic-gate /* convert name to node, and parent path */ 21777c478bd9Sstevel@tonic-gate psvcplugin_lookup(id, parent_path, &child_node); 21787c478bd9Sstevel@tonic-gate /* Device removed */ 21797c478bd9Sstevel@tonic-gate ptree_delete_node(child_node); 21807c478bd9Sstevel@tonic-gate 21817c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 21827c478bd9Sstevel@tonic-gate } 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate 21857c478bd9Sstevel@tonic-gate /* 21867c478bd9Sstevel@tonic-gate * Set absent temperature sensor values to HOTPLUGGED 21877c478bd9Sstevel@tonic-gate */ 21887c478bd9Sstevel@tonic-gate int32_t 21897c478bd9Sstevel@tonic-gate set_temp_sensor_properties(psvc_opaque_t hdlp, char *id) 21907c478bd9Sstevel@tonic-gate { 21917c478bd9Sstevel@tonic-gate char state[32]; 21927c478bd9Sstevel@tonic-gate int32_t status = PSVC_SUCCESS; 21937c478bd9Sstevel@tonic-gate 21947c478bd9Sstevel@tonic-gate status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state); 21957c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 21967c478bd9Sstevel@tonic-gate return (status); 21977c478bd9Sstevel@tonic-gate } 21987c478bd9Sstevel@tonic-gate 21997c478bd9Sstevel@tonic-gate if (strcmp(state, PSVC_HOTPLUGGED) != 0) { 22007c478bd9Sstevel@tonic-gate strcpy(state, PSVC_HOTPLUGGED); 22017c478bd9Sstevel@tonic-gate 22027c478bd9Sstevel@tonic-gate status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 22037c478bd9Sstevel@tonic-gate if (status == PSVC_FAILURE) { 22047c478bd9Sstevel@tonic-gate return (status); 22057c478bd9Sstevel@tonic-gate } 22067c478bd9Sstevel@tonic-gate } 22077c478bd9Sstevel@tonic-gate 22087c478bd9Sstevel@tonic-gate return (PSVC_SUCCESS); 22097c478bd9Sstevel@tonic-gate } 2210