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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * This file contains routines to support the Platform Services Plugin
31 * These routines implement the platform independent environment monitoring
32 * and control policies that may be invoked by a daemon thread within
45 #include <sys/types.h>
50 #include <sys/types.h>
52 #include <psvc_objects.h>
54 #define LOWTEMP_CRITICAL_MSG \
55 gettext("CRITICAL : LOW TEMPERATURE DETECTED %d, %s")
56 #define LOWTEMP_WARNING_MSG \
57 gettext("WARNING : LOW TEMPERATURE DETECTED %d, %s")
58 #define HIGHTEMP_CRITICAL_MSG \
59 gettext("CRITICAL : HIGH TEMPERATURE DETECTED %d, %s")
60 #define HIGHTEMP_WARNING_MSG \
61 gettext("WARNING : HIGH TEMPERATURE DETECTED %d, %s")
62 #define DEVICE_INSERTED_MSG gettext("Device %s inserted")
63 #define DEVICE_REMOVED_MSG gettext("Device %s removed")
64 #define DEVICE_FAILURE_MSG \
65 gettext("CRITICAL: Device %s failure detected by sensor %s\n")
66 #define DEVICE_OK_MSG gettext("Device %s OK")
67 #define SECONDARY_FAN_FAIL_MSG gettext("Secondary fan failure, device %s")
68 #define KEYSWITCH_POS_READ_FAILED_MSG \
69 gettext("Keyswitch position could not be determined")
70 #define KEYSWITCH_POS_CHANGED_MSG gettext("Keyswitch position changed to %s")
71 #define GET_PRESENCE_FAILED_MSG \
72 gettext("Failed to get presence attribute, id = %s, errno = %d\n")
73 #define GET_SENSOR_FAILED_MSG \
74 gettext("Failed to get sensor value, id = %s, errno = %d\n")
75 #define PS_OVER_CURRENT_MSG \
76 gettext("WARNING: Power Supply overcurrent detected for %s\n")
77 #define SET_LED_FAILED_MSG \
78 gettext("Failed to set LED state, id = %s, errno = %d\n")
79 #define SET_FANSPEED_FAILED_MSG \
80 gettext("Failed to set fan speed, id = %s, errno = %d\n")
81 #define FAN_MISSING_MSG \
82 gettext("WARNING: Fan missing, id = %s\n")
83 #define TEMP_SENSOR_FAULT \
84 gettext("WARNING: Temperature Sensor %s returning faulty temp\n")
85 #define TEMP_OFFSET 17
87 static char *shutdown_string
= "shutdown -y -g 60 -i 5 \"OVERTEMP condition\"";
89 static int cpus_online
= 0;
91 typedef struct seg_desc
{
97 static int32_t threshold_names
[] = {
101 PSVC_NOT_USED
, /* LOW MODE which is not used */
102 PSVC_OPTIMAL_TEMP_ATTR
,
109 * The I2C bus is noisy, and the state may be incorrectly reported as
110 * having changed. When the state changes, we attempt to confirm by
111 * retrying. If any retries indicate that the state has not changed, we
112 * assume the state change(s) were incorrect and the state has not changed.
113 * The following variables are used to store the tuneable values read in
114 * from the optional i2cparam.conf file for this shared object library.
116 static int n_read_temp
= PSVC_THRESHOLD_COUNTER
;
117 static int n_retry_keyswitch
= PSVC_NUM_OF_RETRIES
;
118 static int retry_sleep_keyswitch
= 1;
119 static int n_retry_hotplug
= PSVC_NUM_OF_RETRIES
;
120 static int retry_sleep_hotplug
= 1;
121 static int n_retry_fan_hotplug
= PSVC_NUM_OF_RETRIES
;
122 static int retry_sleep_fan_hotplug
= 1;
123 static int n_retry_fan_present
= PSVC_NUM_OF_RETRIES
;
124 static int retry_sleep_fan_present
= 1;
131 static i2c_noise_param_t i2cparams_sun4u
[] = {
132 &n_read_temp
, "n_read_temp",
133 &n_retry_keyswitch
, "n_retry_keyswitch",
134 &retry_sleep_keyswitch
, "retry_sleep_keyswitch",
135 &n_retry_hotplug
, "n_retry_hotplug",
136 &retry_sleep_hotplug
, "retry_sleep_hotplug",
137 &n_retry_fan_hotplug
, "n_retry_fan_hotplug",
138 &retry_sleep_fan_hotplug
, "retry_sleep_fan_hotplug",
139 &n_retry_fan_present
, "n_retry_fan_present",
140 &retry_sleep_fan_present
, "retry_sleep_fan_present",
144 #pragma init(i2cparams_sun4u_load)
147 i2cparams_sun4u_debug(i2c_noise_param_t
*pi2cparams
, int usingDefaults
)
150 i2c_noise_param_t
*p
;
152 if (!usingDefaults
) {
154 "# Values from /usr/platform/sun4u/lib/i2cparam.conf\n",
156 syslog(LOG_WARNING
, "%s", s
);
158 /* no file - we're using the defaults */
160 "# No /usr/platform/sun4u/lib/i2cparam.conf file, using defaults\n",
163 (void) fputs(s
, stdout
);
165 while (p
->pvar
!= NULL
) {
166 (void) snprintf(s
, sizeof (s
), "%s %d\n", p
->texttag
,
169 syslog(LOG_WARNING
, "%s", s
);
170 (void) fputs(s
, stdout
);
176 i2cparams_sun4u_load(void)
179 char *filename
= "/usr/platform/sun4u/lib/i2cparam.conf";
183 i2c_noise_param_t
*p
;
185 /* read thru the i2cparam.conf file and set variables */
186 if ((fp
= fopen(filename
, "r")) != NULL
) {
187 while (fgets(s
, sizeof (s
), fp
) != NULL
) {
188 if (s
[0] == '#') /* skip comment lines */
190 /* try to find a string match and get the value */
191 if (sscanf(s
, "%127s %d", var
, &val
) != 2)
194 val
= 1; /* clamp min value */
195 p
= &(i2cparams_sun4u
[0]);
196 while (p
->pvar
!= NULL
) {
197 if (strncmp(p
->texttag
, var
, sizeof (var
)) ==
207 /* output the values of the parameters */
208 i2cparams_sun4u_debug(&(i2cparams_sun4u
[0]), ((fp
== NULL
)? 1 : 0));
213 psvc_update_thresholds_0(psvc_opaque_t hdlp
, char *id
)
215 int32_t status
= PSVC_SUCCESS
;
217 char *fru
, seg_name
[2];
218 int8_t seg_count
, temp_array
[8];
219 int32_t match_count
, i
, j
, seg_desc_start
= 0x1806, temp_address
;
220 int32_t seg_found
, temp
;
224 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &present
);
225 if ((status
!= PSVC_SUCCESS
) || (present
!= PSVC_PRESENT
))
228 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &match_count
,
230 if (status
== PSVC_FAILURE
)
233 for (i
= 0; i
< match_count
; i
++) {
235 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
237 if (status
!= PSVC_SUCCESS
)
240 fru_data
.buf_start
= 0x1805;
241 fru_data
.buf
= (char *)&seg_count
;
242 fru_data
.read_size
= 1;
244 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
246 if (status
!= PSVC_SUCCESS
) {
249 for (j
= 0; (j
< seg_count
) && (!seg_found
); j
++) {
250 fru_data
.buf_start
= seg_desc_start
;
251 fru_data
.buf
= seg_name
;
252 fru_data
.read_size
= 2;
254 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
257 seg_desc_start
= seg_desc_start
+ 2;
258 fru_data
.buf_start
= seg_desc_start
;
259 fru_data
.buf
= (char *)&segment
;
260 fru_data
.read_size
= sizeof (seg_desc_t
);
262 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
264 if (status
!= PSVC_SUCCESS
) {
266 "Failed psvc_get_attr for FRU info\n");
269 seg_desc_start
= seg_desc_start
+ sizeof (seg_desc_t
);
270 if (memcmp(seg_name
, "SC", 2) == 0)
274 temp_address
= segment
.segoffset
+ TEMP_OFFSET
;
275 fru_data
.buf_start
= temp_address
;
276 fru_data
.buf
= (char *)&temp_array
;
277 fru_data
.read_size
= sizeof (temp_array
);
278 status
= psvc_get_attr(hdlp
, fru
, PSVC_FRU_INFO_ATTR
,
280 if (status
!= PSVC_SUCCESS
) {
282 "Failed psvc_get_attr for FRU info\n");
285 for (j
= 0; j
< sizeof (temp_array
); j
++) {
286 if (threshold_names
[j
] == PSVC_NOT_USED
)
288 temp
= temp_array
[j
];
289 status
= psvc_set_attr(hdlp
, id
,
290 threshold_names
[j
], &temp
);
291 if (status
!= PSVC_SUCCESS
) {
297 syslog(LOG_ERR
, "No FRU Information for %s"
298 " using default temperatures\n", id
);
304 #define MAX_TEMP_SENSORS 256
307 check_temp(psvc_opaque_t hdlp
, char *id
, int32_t silent
)
309 int32_t lo_warn
, hi_warn
, lo_shut
, hi_shut
;
312 char previous_state
[32];
318 int32_t status
= PSVC_SUCCESS
;
320 static int threshold_low_shut
[MAX_TEMP_SENSORS
] = {0};
321 static int threshold_high_shut
[MAX_TEMP_SENSORS
] = {0};
322 static int threshold_low_warn
[MAX_TEMP_SENSORS
] = {0};
323 static int threshold_high_warn
[MAX_TEMP_SENSORS
] = {0};
326 status
= psvc_get_attr(hdlp
, id
, PSVC_INSTANCE_ATTR
, &instance
);
327 if (status
!= PSVC_SUCCESS
)
330 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &pr
);
331 if ((status
!= PSVC_SUCCESS
) || (pr
!= PSVC_PRESENT
)) {
335 status
= psvc_get_attr(hdlp
, id
, PSVC_STATE_ATTR
, state
);
336 if (status
== PSVC_FAILURE
)
339 if ((strcmp(state
, PSVC_HOTPLUGGED
) == 0)) {
340 return (PSVC_SUCCESS
);
343 status
= psvc_get_attr(hdlp
, id
, PSVC_FEATURES_ATTR
, &features
);
344 if (status
!= PSVC_SUCCESS
)
347 status
= psvc_get_attr(hdlp
, id
, PSVC_LO_WARN_ATTR
, &lo_warn
);
348 if (status
!= PSVC_SUCCESS
)
351 status
= psvc_get_attr(hdlp
, id
, PSVC_LO_SHUT_ATTR
, &lo_shut
);
352 if (status
!= PSVC_SUCCESS
)
355 status
= psvc_get_attr(hdlp
, id
, PSVC_HI_WARN_ATTR
, &hi_warn
);
356 if (status
!= PSVC_SUCCESS
)
359 status
= psvc_get_attr(hdlp
, id
, PSVC_HI_SHUT_ATTR
, &hi_shut
);
360 if (status
!= PSVC_SUCCESS
)
363 status
= psvc_get_attr(hdlp
, id
, PSVC_SENSOR_VALUE_ATTR
, &temp
);
364 if (status
!= PSVC_SUCCESS
) {
369 * The following code is to check to see if the temp sensor is
370 * returning a faulty reading due to it either being bad or the
371 * CPU being powered off for some reason. Is so we will alert the user
372 * and just label the sensor bad but not the WHOLE CPU module.
374 if ((temp
== 127) && (strcmp(state
, PSVC_ERROR
) != 0)) {
375 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, PSVC_ERROR
);
376 if (status
!= PSVC_SUCCESS
)
378 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
,
380 if (status
!= PSVC_SUCCESS
)
382 syslog(LOG_ERR
, TEMP_SENSOR_FAULT
, id
);
386 status
= psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, label
);
387 if (status
!= PSVC_SUCCESS
)
391 * if any of the four temperature states (lo_shut, lo_warn,
392 * hi_shut, hi_warn) is detected we will not take an action
393 * until the number of similar back-to-back readings equals
394 * 'n_read_temp' (default is PSVC_THRESHOLD_COUNTER).
396 if ((features
& PSVC_LOW_SHUT
) && temp
< lo_shut
) {
398 * once we are in one state, clear all the
399 * counters for the other three states since
400 * back-to-back readings of these other three
401 * states could not happen anymore.
403 threshold_low_warn
[instance
] = 0;
404 threshold_high_shut
[instance
] = 0;
405 threshold_high_warn
[instance
] = 0;
406 threshold_low_shut
[instance
]++;
407 if (threshold_low_shut
[instance
] == n_read_temp
) {
408 threshold_low_shut
[instance
] = 0;
410 strcpy(state
, PSVC_ERROR
);
411 strcpy(fault
, PSVC_TEMP_LO_SHUT
);
412 strcpy(led_state
, PSVC_LED_ON
);
414 syslog(LOG_ERR
, LOWTEMP_CRITICAL_MSG
,
416 } else { /* Threshold for showing error not reached */
417 return (PSVC_SUCCESS
);
419 } else if ((features
& PSVC_LOW_WARN
) && temp
< lo_warn
) {
420 threshold_low_shut
[instance
] = 0;
421 threshold_high_shut
[instance
] = 0;
422 threshold_high_warn
[instance
] = 0;
423 threshold_low_warn
[instance
]++;
424 if (threshold_low_warn
[instance
] == n_read_temp
) {
425 threshold_low_warn
[instance
] = 0;
427 strcpy(state
, PSVC_ERROR
);
428 strcpy(fault
, PSVC_TEMP_LO_WARN
);
429 strcpy(led_state
, PSVC_LED_ON
);
431 syslog(LOG_ERR
, LOWTEMP_WARNING_MSG
,
433 } else { /* Threshold for showing error not reached */
434 return (PSVC_SUCCESS
);
436 } else if ((features
& PSVC_HIGH_SHUT
) && temp
> hi_shut
) {
437 threshold_low_warn
[instance
] = 0;
438 threshold_low_shut
[instance
] = 0;
439 threshold_high_warn
[instance
] = 0;
440 threshold_high_shut
[instance
]++;
441 if (threshold_high_shut
[instance
] == n_read_temp
) {
442 threshold_high_shut
[instance
] = 0;
444 strcpy(state
, PSVC_ERROR
);
445 strcpy(fault
, PSVC_TEMP_HI_SHUT
);
446 strcpy(led_state
, PSVC_LED_ON
);
448 syslog(LOG_ERR
, HIGHTEMP_CRITICAL_MSG
,
450 } else { /* Threshold for showing error not reached */
451 return (PSVC_SUCCESS
);
453 } else if ((features
& PSVC_HIGH_WARN
) && temp
> hi_warn
) {
454 threshold_low_warn
[instance
] = 0;
455 threshold_low_shut
[instance
] = 0;
456 threshold_high_shut
[instance
] = 0;
457 threshold_high_warn
[instance
]++;
458 if (threshold_high_warn
[instance
] == n_read_temp
) {
459 threshold_high_warn
[instance
] = 0;
461 strcpy(state
, PSVC_ERROR
);
462 strcpy(fault
, PSVC_TEMP_HI_WARN
);
463 strcpy(led_state
, PSVC_LED_ON
);
465 syslog(LOG_ERR
, HIGHTEMP_WARNING_MSG
,
467 } else { /* Threshold for showing error not reached */
468 return (PSVC_SUCCESS
);
473 * If we reached this point then that means that we are either
474 * okay, or we have showed error n_read_temp times.
478 strcpy(state
, PSVC_OK
);
479 strcpy(fault
, PSVC_NO_FAULT
);
480 strcpy(led_state
, PSVC_LED_OFF
);
483 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, state
);
484 if (status
!= PSVC_SUCCESS
)
486 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
, fault
);
487 if (status
!= PSVC_SUCCESS
)
489 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_STATE_ATTR
,
491 if (status
!= PSVC_SUCCESS
)
494 if (strcmp(previous_state
, state
) != 0) {
499 /* change state of fault LEDs */
500 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &led_count
,
501 PSVC_TS_OVERTEMP_LED
);
502 for (i
= 0; i
< led_count
; ++i
) {
503 status
= psvc_get_attr(hdlp
, id
,
504 PSVC_ASSOC_ID_ATTR
, &led_id
,
505 PSVC_TS_OVERTEMP_LED
, i
);
506 if (status
== PSVC_FAILURE
)
508 status
= psvc_set_attr(hdlp
, led_id
,
509 PSVC_LED_STATE_ATTR
, led_state
);
510 if (status
== PSVC_FAILURE
)
515 return (PSVC_SUCCESS
);
519 psvc_check_temperature_policy_0(psvc_opaque_t hdlp
, char *id
)
521 return (check_temp(hdlp
, id
, 0));
525 psvc_check_temperature_silent_policy_0(psvc_opaque_t hdlp
, char *id
)
527 return (check_temp(hdlp
, id
, 1));
531 psvc_fan_enable_disable_policy_0(psvc_opaque_t hdlp
, char *id
)
533 char state
[32], previous_state
[32];
535 int32_t status
= PSVC_SUCCESS
;
542 status
= psvc_get_attr(hdlp
, id
, PSVC_FEATURES_ATTR
, &features
);
543 if (status
!= PSVC_SUCCESS
)
549 (void) sleep(retry_sleep_fan_present
);
551 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &presence
);
552 if (status
!= PSVC_SUCCESS
)
555 } while ((retry
< n_retry_fan_present
) && (presence
== PSVC_ABSENT
));
557 if (presence
== PSVC_ABSENT
) {
558 status
= psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, label
);
559 if (status
!= PSVC_SUCCESS
)
562 status
= psvc_get_attr(hdlp
, id
, PSVC_ENABLE_ATTR
, &enable
);
563 if (status
!= PSVC_SUCCESS
)
566 if (features
& PSVC_DEV_PRIMARY
) {
567 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
568 &backup_fan
, PSVC_ALTERNATE
, 0);
569 if (status
!= PSVC_SUCCESS
)
572 enable
= PSVC_DISABLED
;
573 status
= psvc_set_attr(hdlp
, id
, PSVC_ENABLE_ATTR
,
575 if (status
!= PSVC_SUCCESS
)
578 enable
= PSVC_ENABLED
;
579 status
= psvc_set_attr(hdlp
, backup_fan
,
580 PSVC_ENABLE_ATTR
, &enable
);
581 if (status
!= PSVC_SUCCESS
)
584 enable
= PSVC_DISABLED
;
585 status
= psvc_set_attr(hdlp
, id
, PSVC_ENABLE_ATTR
,
587 if (status
!= PSVC_SUCCESS
)
590 return (PSVC_SUCCESS
);
593 /* device was present */
594 status
= psvc_get_attr(hdlp
, id
, PSVC_STATE_ATTR
, state
);
595 if (status
!= PSVC_SUCCESS
)
598 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_STATE_ATTR
, previous_state
);
599 if (status
!= PSVC_SUCCESS
)
602 if (features
& PSVC_DEV_PRIMARY
) {
603 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
604 &backup_fan
, PSVC_ALTERNATE
, 0);
605 if (status
!= PSVC_SUCCESS
)
608 if (strcmp(state
, PSVC_OK
) == 0) {
609 enable
= PSVC_ENABLED
;
610 status
= psvc_set_attr(hdlp
, id
, PSVC_ENABLE_ATTR
,
612 if (status
!= PSVC_SUCCESS
)
615 enable
= PSVC_DISABLED
;
616 status
= psvc_set_attr(hdlp
, backup_fan
,
617 PSVC_ENABLE_ATTR
, &enable
);
618 if (status
!= PSVC_SUCCESS
)
621 if ((strcmp(state
, PSVC_ERROR
) == 0) &&
622 (strcmp(previous_state
, PSVC_ERROR
) != 0)) {
623 enable
= PSVC_DISABLED
;
624 status
= psvc_set_attr(hdlp
, id
, PSVC_ENABLE_ATTR
,
626 if (status
!= PSVC_SUCCESS
)
629 enable
= PSVC_ENABLED
;
630 status
= psvc_set_attr(hdlp
, backup_fan
,
631 PSVC_ENABLE_ATTR
, &enable
);
632 if (status
!= PSVC_SUCCESS
)
636 if ((strcmp(state
, PSVC_ERROR
) == 0) &&
637 (strcmp(previous_state
, PSVC_ERROR
) != 0)) {
638 status
= psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
,
640 if (status
!= PSVC_SUCCESS
)
642 syslog(LOG_ERR
, SECONDARY_FAN_FAIL_MSG
, label
);
649 * psvc_switch_fan_onoff_policy_0
650 * Turn a fan on if it is enabled, turn it off if it is disabled.
653 psvc_switch_fan_onoff_policy_0(psvc_opaque_t hdlp
, char *id
)
658 int32_t status
= PSVC_SUCCESS
;
660 status
= psvc_get_attr(hdlp
, id
, PSVC_ENABLE_ATTR
, &enable
);
661 if (status
!= PSVC_SUCCESS
)
664 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
, &switchid
,
665 PSVC_FAN_ONOFF_SENSOR
, 0);
666 if (status
!= PSVC_SUCCESS
)
669 if (enable
== PSVC_DISABLED
) {
670 strcpy(state
, PSVC_SWITCH_OFF
);
672 strcpy(state
, PSVC_SWITCH_ON
);
675 status
= psvc_set_attr(hdlp
, switchid
, PSVC_SWITCH_STATE_ATTR
, state
);
680 check_cpu_temp_fault(psvc_opaque_t hdlp
, char *cpu
, int32_t cpu_count
)
683 int32_t sensor_count
;
684 int32_t status
= PSVC_SUCCESS
;
689 status
= psvc_get_attr(hdlp
, cpu
, PSVC_FEATURES_ATTR
, &features
);
690 if (status
== PSVC_FAILURE
)
693 psvc_get_attr(hdlp
, cpu
, PSVC_ASSOC_MATCHES_ATTR
, &sensor_count
,
694 PSVC_DEV_TEMP_SENSOR
);
695 for (i
= 0; i
< sensor_count
; ++i
) {
696 status
= psvc_get_attr(hdlp
, cpu
, PSVC_ASSOC_ID_ATTR
,
697 &sensorid
, PSVC_DEV_TEMP_SENSOR
, i
);
698 if (status
== PSVC_FAILURE
)
701 status
= psvc_get_attr(hdlp
, sensorid
, PSVC_FAULTID_ATTR
,
703 if (status
== PSVC_FAILURE
)
706 if ((strcmp(fault
, PSVC_TEMP_HI_SHUT
) == 0) ||
707 (strcmp(fault
, PSVC_TEMP_LO_SHUT
) == 0)) {
708 if (cpu_count
== 1 || cpus_online
== 1 ||
709 !(features
& PSVC_DEV_HOTPLUG
)) {
710 system(shutdown_string
);
712 /* FIX offline cpu */
722 psvc_shutdown_policy_0(psvc_opaque_t hdlp
, char *id
)
728 int32_t status
= PSVC_SUCCESS
;
730 if (cpus_online
== 0) {
731 /* obviously, zero isn't correct, count present cpu's */
732 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &cpu_count
,
734 for (i
= 0; i
< cpu_count
; ++i
) {
735 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
736 &cpuid
, PSVC_CPU
, i
);
737 if (status
== PSVC_FAILURE
)
740 status
= psvc_get_attr(hdlp
, cpuid
,
741 PSVC_PRESENCE_ATTR
, &present
);
742 if (status
== PSVC_FAILURE
&& present
== PSVC_PRESENT
)
744 if (present
== PSVC_PRESENT
)
748 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &cpu_count
,
750 for (i
= 0; i
< cpu_count
; ++i
) {
751 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
, &cpuid
,
753 if (status
== PSVC_FAILURE
)
755 status
= check_cpu_temp_fault(hdlp
, cpuid
, cpu_count
);
756 if (status
== PSVC_FAILURE
&& errno
!= ENODEV
)
760 return (PSVC_SUCCESS
);
764 * psvc_keyswitch_position_policy_0
765 * Checks the state of the keyswitch sensors.
766 * If a keyswitch position sensor's state is on, the position
767 * of the key is written to syslog. If none of the sensors
768 * are on (keyswitch is not at one of the detents), a message is sent
769 * to syslog stating that the position is unknown.
772 psvc_keyswitch_position_policy_0(psvc_opaque_t hdlp
, char *id
)
775 int32_t status
= PSVC_SUCCESS
;
776 static int error_reported
= 0;
777 static char local_previous_position
[32];
778 static int32_t first_time
= 1;
783 status
= psvc_get_attr(hdlp
, id
, PSVC_STATE_ATTR
,
784 local_previous_position
);
785 if (status
!= PSVC_SUCCESS
)
792 (void) sleep(retry_sleep_keyswitch
);
794 status
= psvc_get_attr(hdlp
, id
, PSVC_SWITCH_STATE_ATTR
,
796 if (status
!= PSVC_SUCCESS
)
799 if (strcmp(position
, PSVC_ERROR
) == 0) {
800 if ((errno
== EINVAL
) && (!(error_reported
))) {
802 KEYSWITCH_POS_READ_FAILED_MSG
);
804 return (PSVC_SUCCESS
);
808 } while ((retry
< n_retry_keyswitch
) &&
809 (strcmp(position
, local_previous_position
) != 0));
811 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, position
);
812 if (status
!= PSVC_SUCCESS
)
815 if (strcmp(position
, local_previous_position
) != 0) {
817 strcpy(local_previous_position
, position
);
818 syslog(LOG_ERR
, KEYSWITCH_POS_CHANGED_MSG
, position
);
825 psvc_hotplug_notifier_policy_0(psvc_opaque_t hdlp
, char *id
)
827 boolean_t presence
, previous_presence
;
828 int32_t status
= PSVC_SUCCESS
;
832 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_PRESENCE_ATTR
,
834 if (status
!= PSVC_SUCCESS
)
840 (void) sleep(retry_sleep_hotplug
);
841 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &presence
);
842 if (status
!= PSVC_SUCCESS
)
845 } while ((retry
< n_retry_hotplug
) &&
846 (presence
!= previous_presence
));
849 if (presence
!= previous_presence
) {
850 char parent_path
[256];
851 picl_nodehdl_t child_node
;
853 status
= psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, label
);
854 if (status
!= PSVC_SUCCESS
)
857 /* return parent path and node for an object */
858 psvcplugin_lookup(id
, parent_path
, &child_node
);
860 if (presence
== PSVC_PRESENT
) {
861 char state
[32], fault
[32];
862 picl_nodehdl_t parent_node
;
864 syslog(LOG_ERR
, DEVICE_INSERTED_MSG
, label
);
865 strcpy(state
, PSVC_OK
);
866 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
,
868 if (status
!= PSVC_SUCCESS
)
870 strcpy(fault
, PSVC_NO_FAULT
);
871 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
,
873 if (status
!= PSVC_SUCCESS
) {
877 status
= ptree_get_node_by_path(parent_path
,
880 return (PSVC_FAILURE
);
881 status
= ptree_add_node(parent_node
, child_node
);
883 return (PSVC_FAILURE
);
885 syslog(LOG_ERR
, DEVICE_REMOVED_MSG
, label
);
887 ptree_delete_node(child_node
);
892 status
= psvc_set_attr(hdlp
, id
, PSVC_PREV_PRESENCE_ATTR
, &presence
);
893 if (status
!= PSVC_SUCCESS
)
900 psvc_fan_hotplug_policy_0(psvc_opaque_t hdlp
, char *id
)
902 boolean_t presence
, previous_presence
;
903 int32_t status
= PSVC_SUCCESS
;
907 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_PRESENCE_ATTR
,
909 if (status
!= PSVC_SUCCESS
)
915 (void) sleep(retry_sleep_fan_hotplug
);
917 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &presence
);
918 if (status
!= PSVC_SUCCESS
)
921 } while ((retry
< n_retry_fan_hotplug
) &&
922 (presence
!= previous_presence
));
925 if (presence
!= previous_presence
) {
926 char parent_path
[256];
927 picl_nodehdl_t child_node
;
929 status
= psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, label
);
930 if (status
!= PSVC_SUCCESS
)
933 /* return parent path and node for an object */
934 psvcplugin_lookup(id
, parent_path
, &child_node
);
936 if (presence
== PSVC_PRESENT
) {
937 char state
[32], fault
[32];
940 int32_t i
, led_count
;
942 picl_nodehdl_t parent_node
;
944 syslog(LOG_ERR
, DEVICE_INSERTED_MSG
, label
);
946 strcpy(state
, PSVC_OK
);
947 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
,
949 if (status
!= PSVC_SUCCESS
)
951 strcpy(fault
, PSVC_NO_FAULT
);
952 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
,
954 if (status
!= PSVC_SUCCESS
)
957 /* turn off fault LEDs */
958 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
,
959 &led_count
, PSVC_DEV_FAULT_LED
);
960 strcpy(led_state
, PSVC_LED_OFF
);
961 for (i
= 0; i
< led_count
; ++i
) {
962 status
= psvc_get_attr(hdlp
, id
,
963 PSVC_ASSOC_ID_ATTR
, &led_id
,
964 PSVC_DEV_FAULT_LED
, i
);
965 if (status
== PSVC_FAILURE
)
967 status
= psvc_set_attr(hdlp
, led_id
,
968 PSVC_LED_STATE_ATTR
, led_state
);
969 if (status
== PSVC_FAILURE
)
973 /* turn off OK to remove LEDs */
974 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
975 &slot_id
, PSVC_PARENT
, 0);
976 if (status
!= PSVC_SUCCESS
)
979 psvc_get_attr(hdlp
, slot_id
, PSVC_ASSOC_MATCHES_ATTR
,
980 &led_count
, PSVC_SLOT_REMOVE_LED
);
981 strcpy(led_state
, PSVC_LED_OFF
);
982 for (i
= 0; i
< led_count
; ++i
) {
983 status
= psvc_get_attr(hdlp
, slot_id
,
984 PSVC_ASSOC_ID_ATTR
, &led_id
,
985 PSVC_SLOT_REMOVE_LED
, i
);
986 if (status
== PSVC_FAILURE
)
989 status
= psvc_set_attr(hdlp
, led_id
,
990 PSVC_LED_STATE_ATTR
, led_state
);
991 if (status
== PSVC_FAILURE
)
995 ptree_get_node_by_path(parent_path
, &parent_node
);
996 ptree_add_node(parent_node
, child_node
);
998 syslog(LOG_ERR
, DEVICE_REMOVED_MSG
, label
);
999 ptree_delete_node(child_node
);
1003 status
= psvc_set_attr(hdlp
, id
, PSVC_PREV_PRESENCE_ATTR
, &presence
);
1004 if (status
!= PSVC_SUCCESS
)
1011 psvc_init_led_policy_0(psvc_opaque_t hdlp
, char *id
)
1015 status
= psvc_set_attr(hdlp
, id
, PSVC_LED_STATE_ATTR
, PSVC_LED_OFF
);
1020 psvc_init_state_policy_0(psvc_opaque_t hdlp
, char *id
)
1024 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, PSVC_OK
);
1025 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
, PSVC_NO_FAULT
);
1030 psvc_ps_overcurrent_check_policy_0(psvc_opaque_t hdlp
, char *power_supply_id
)
1032 int32_t status
= PSVC_SUCCESS
;
1035 int32_t sensor_count
;
1037 int32_t amps
, hi_warn
;
1039 status
= psvc_get_attr(hdlp
, power_supply_id
, PSVC_PRESENCE_ATTR
,
1041 if (status
== PSVC_FAILURE
) {
1042 syslog(LOG_ERR
, GET_PRESENCE_FAILED_MSG
, power_supply_id
,
1047 if (present
== PSVC_ABSENT
) {
1049 return (PSVC_FAILURE
);
1052 psvc_get_attr(hdlp
, power_supply_id
, PSVC_ASSOC_MATCHES_ATTR
,
1053 &sensor_count
, PSVC_PS_I_SENSOR
);
1054 for (i
= 0; i
< sensor_count
; ++i
) {
1055 status
= psvc_get_attr(hdlp
, power_supply_id
,
1056 PSVC_ASSOC_ID_ATTR
, &sensor_id
, PSVC_PS_I_SENSOR
, i
);
1057 if (status
!= PSVC_SUCCESS
)
1060 status
= psvc_get_attr(hdlp
, sensor_id
, PSVC_HI_WARN_ATTR
,
1062 if (status
!= PSVC_SUCCESS
)
1065 status
= psvc_get_attr(hdlp
, sensor_id
,
1066 PSVC_SENSOR_VALUE_ATTR
, &s
);
1067 if (status
!= PSVC_SUCCESS
) {
1068 syslog(LOG_ERR
, GET_SENSOR_FAILED_MSG
, sensor_id
,
1073 if (amps
>= hi_warn
) {
1076 status
= psvc_get_attr(hdlp
, power_supply_id
,
1077 PSVC_LABEL_ATTR
, &label
);
1078 if (status
!= PSVC_SUCCESS
)
1081 syslog(LOG_ERR
, PS_OVER_CURRENT_MSG
, label
);
1085 return (PSVC_SUCCESS
);
1090 psvc_device_fail_notifier_policy_0(psvc_opaque_t hdlp
, char *id
)
1092 int32_t led_count
, sensor_count
;
1093 char *led_id
, *sensor_id
;
1095 char state
[32], fault
[32], previous_state
[32];
1097 int32_t status
= PSVC_SUCCESS
;
1100 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &present
);
1101 if (status
== PSVC_FAILURE
)
1104 if (present
== PSVC_ABSENT
) {
1106 return (PSVC_FAILURE
);
1109 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
, &sensor_count
,
1110 PSVC_DEV_FAULT_SENSOR
);
1111 for (i
= 0; i
< sensor_count
; ++i
) {
1112 status
= psvc_get_attr(hdlp
, id
, PSVC_ASSOC_ID_ATTR
,
1113 &sensor_id
, PSVC_DEV_FAULT_SENSOR
, i
);
1114 if (status
!= PSVC_SUCCESS
)
1117 status
= psvc_get_attr(hdlp
, sensor_id
,
1118 PSVC_SWITCH_STATE_ATTR
, state
);
1119 if (status
!= PSVC_SUCCESS
)
1122 if (strcmp(state
, PSVC_SWITCH_ON
) == 0) {
1123 strcpy(state
, PSVC_ERROR
);
1124 strcpy(fault
, PSVC_GEN_FAULT
);
1126 strcpy(state
, PSVC_OK
);
1127 strcpy(fault
, PSVC_NO_FAULT
);
1130 status
= psvc_set_attr(hdlp
, id
, PSVC_STATE_ATTR
, state
);
1131 if (status
!= PSVC_SUCCESS
)
1133 status
= psvc_set_attr(hdlp
, id
, PSVC_FAULTID_ATTR
, fault
);
1134 if (status
!= PSVC_SUCCESS
)
1136 status
= psvc_get_attr(hdlp
, id
, PSVC_PREV_STATE_ATTR
,
1138 if (status
!= PSVC_SUCCESS
)
1141 if (strcmp(state
, previous_state
) != 0) {
1142 char sensor_label
[32];
1146 psvc_get_attr(hdlp
, id
, PSVC_LABEL_ATTR
, dev_label
);
1147 psvc_get_attr(hdlp
, sensor_id
, PSVC_LABEL_ATTR
,
1150 if (strcmp(state
, PSVC_ERROR
) == 0) {
1151 syslog(LOG_ERR
, DEVICE_FAILURE_MSG
, dev_label
,
1153 strcpy(led_state
, PSVC_LED_ON
);
1155 syslog(LOG_ERR
, DEVICE_OK_MSG
, dev_label
);
1156 strcpy(led_state
, PSVC_LED_OFF
);
1159 psvc_get_attr(hdlp
, id
, PSVC_ASSOC_MATCHES_ATTR
,
1160 &led_count
, PSVC_DEV_FAULT_LED
);
1161 for (j
= 0; j
< led_count
; j
++) {
1162 status
= psvc_get_attr(hdlp
, id
,
1163 PSVC_ASSOC_ID_ATTR
, &led_id
,
1164 PSVC_DEV_FAULT_LED
, j
);
1165 if (status
!= PSVC_SUCCESS
)
1167 status
= psvc_set_attr(hdlp
, led_id
,
1168 PSVC_LED_STATE_ATTR
, led_state
);
1169 if (status
!= PSVC_SUCCESS
) {
1170 syslog(LOG_ERR
, SET_LED_FAILED_MSG
,
1178 return (PSVC_SUCCESS
);
1182 get_filtered_error(float *last_errors
, int current_error
)
1188 adder
= last_errors
[0];
1189 for (i
= 1; i
< PSVC_MAXERRORS
; i
++) {
1190 adder
= adder
+ last_errors
[i
];
1192 adder
= adder
+ current_error
;
1193 error
= adder
/(PSVC_MAXERRORS
+1);
1199 change_cpu_fans(psvc_opaque_t hdlp
, char *fan_id
, int32_t fan_speed
)
1201 int err
= PSVC_SUCCESS
;
1203 int32_t control_count
;
1205 int32_t old_fan_speed
;
1207 psvc_get_attr(hdlp
, fan_id
, PSVC_ASSOC_MATCHES_ATTR
, &control_count
,
1208 PSVC_FAN_DRIVE_CONTROL
);
1209 if (control_count
== 0)
1210 return (PSVC_SUCCESS
);
1212 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_ASSOC_ID_ATTR
, &control_id
,
1213 PSVC_FAN_DRIVE_CONTROL
, 0);
1214 if (err
!= PSVC_SUCCESS
)
1218 * this call will return PSVC_FAILURE on the first pass,
1219 * because no value has been set.
1221 err
= psvc_get_attr(hdlp
, control_id
, PSVC_CONTROL_VALUE_ATTR
,
1223 if (err
== PSVC_SUCCESS
&& old_fan_speed
== fan_speed
)
1224 return (PSVC_SUCCESS
);
1226 for (i
= 0; i
< control_count
; i
++) {
1227 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_ASSOC_ID_ATTR
,
1228 &control_id
, PSVC_FAN_DRIVE_CONTROL
, i
);
1229 if (err
!= PSVC_SUCCESS
)
1232 err
= psvc_set_attr(hdlp
, control_id
, PSVC_CONTROL_VALUE_ATTR
,
1234 if (err
== PSVC_FAILURE
) {
1235 syslog(LOG_ERR
, SET_FANSPEED_FAILED_MSG
, control_id
,
1244 device_temp_check(psvc_opaque_t hdlp
, char *fan_id
, int32_t *hot_device
)
1247 int32_t err
= PSVC_SUCCESS
;
1249 int32_t sensor_count
;
1254 psvc_get_attr(hdlp
, fan_id
, PSVC_ASSOC_MATCHES_ATTR
, &sensor_count
,
1255 PSVC_DEV_TEMP_SENSOR
);
1256 for (i
= 0; i
< sensor_count
; i
++) {
1257 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_ASSOC_ID_ATTR
,
1258 &sensor_id
, PSVC_DEV_TEMP_SENSOR
, i
);
1259 if (err
== PSVC_FAILURE
)
1261 err
= psvc_get_attr(hdlp
, sensor_id
, PSVC_SENSOR_VALUE_ATTR
,
1263 if (err
== PSVC_FAILURE
) {
1264 if (errno
== ENODEV
) {
1267 syslog(LOG_ERR
, GET_SENSOR_FAILED_MSG
,
1273 if (*hot_device
< temp
)
1276 return (PSVC_SUCCESS
);
1280 psvc_fan_control_policy_0(psvc_opaque_t hdlp
, char *fan_id
)
1282 boolean_t is_enabled
;
1283 int32_t err
= PSVC_SUCCESS
;
1284 int16_t setpoint
, hysteresis
, loopgain
, loopbias
;
1285 int current_error
; /* Holds current error */
1286 /* Signal before signaling */
1287 float filtered_error
; /* Holds the filtered error signal */
1288 int ampout
; /* output of loop amplifier */
1291 int16_t error_number
;
1292 float last_errors
[PSVC_MAXERRORS
]; /* Holds the filtered error */
1293 /* from the last n iterations */
1295 psvc_get_attr(hdlp
, fan_id
, PSVC_ENABLE_ATTR
, &is_enabled
);
1296 if (is_enabled
== PSVC_DISABLED
)
1297 return (PSVC_SUCCESS
);
1299 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_SETPOINT_ATTR
, &setpoint
);
1300 if (err
!= PSVC_SUCCESS
)
1303 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_HYSTERESIS_ATTR
,
1305 if (err
!= PSVC_SUCCESS
)
1308 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_LOOPGAIN_ATTR
, &loopgain
);
1309 if (err
!= PSVC_SUCCESS
)
1312 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_LOOPBIAS_ATTR
, &loopbias
);
1313 if (err
!= PSVC_SUCCESS
)
1316 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_TEMP_DIFFERENTIAL_ATTR
,
1318 if (err
!= PSVC_SUCCESS
)
1321 err
= psvc_get_attr(hdlp
, fan_id
, PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR
,
1323 if (err
!= PSVC_SUCCESS
)
1326 err
= device_temp_check(hdlp
, fan_id
, &hot_device
);
1327 if (err
!= PSVC_SUCCESS
) {
1328 printf("psvc_fan_control failure in device_temp_check\n");
1331 current_error
= setpoint
- hot_device
;
1332 filtered_error
= get_filtered_error(last_errors
, current_error
);
1333 if (filtered_error
<= 0 || filtered_error
> hysteresis
) {
1334 ampout
= (int)((filtered_error
* loopgain
) + loopbias
);
1339 err
= change_cpu_fans(hdlp
, fan_id
, ampout
);
1340 if (err
!= PSVC_SUCCESS
)
1343 last_errors
[error_number
++] = current_error
;
1344 if (error_number
== PSVC_MAXERRORS
)
1347 err
= psvc_set_attr(hdlp
, fan_id
, PSVC_TEMP_DIFFERENTIAL_ATTR
,
1349 if (err
!= PSVC_SUCCESS
)
1352 err
= psvc_set_attr(hdlp
, fan_id
, PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR
,
1354 if (err
!= PSVC_SUCCESS
)
1357 return (PSVC_SUCCESS
);
1361 psvc_fan_present_policy_0(psvc_opaque_t hdlp
, char *id
)
1363 int32_t status
= PSVC_SUCCESS
;
1372 (void) sleep(retry_sleep_fan_present
);
1374 status
= psvc_get_attr(hdlp
, id
, PSVC_PRESENCE_ATTR
, &presence
);
1375 if (status
!= PSVC_SUCCESS
)
1378 } while ((retry
< n_retry_fan_present
) && (presence
== PSVC_ABSENT
));
1380 if (presence
== PSVC_ABSENT
) {
1382 * We make this open, write, close, call because picld
1383 * starts in rcS.d while print services does not start
1384 * until later (either rc2.d or rc3.d)
1386 fd
= open("/dev/console", O_WRONLY
| O_NOCTTY
);
1388 fp
= fdopen(fd
, "w+");
1390 fprintf(fp
, FAN_MISSING_MSG
, id
);
1395 syslog(LOG_ERR
, FAN_MISSING_MSG
, id
);