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