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 /* 28 * This file contains routines to support the Platform Services Plugin 29 * These routines implement the platform independent environment monitoring 30 * and control policies that may be invoked by a daemon thread within 31 * the plugin 32 */ 33 34 #include <syslog.h> 35 #include <unistd.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <libintl.h> 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <strings.h> 42 #include <libintl.h> 43 #include <sys/types.h> 44 #include <string.h> 45 #include <limits.h> 46 #include <picl.h> 47 #include <picltree.h> 48 #include <sys/types.h> 49 #include <string.h> 50 #include <psvc_objects.h> 51 52 #define LOWTEMP_CRITICAL_MSG \ 53 gettext("CRITICAL : LOW TEMPERATURE DETECTED %d, %s") 54 #define LOWTEMP_WARNING_MSG \ 55 gettext("WARNING : LOW TEMPERATURE DETECTED %d, %s") 56 #define HIGHTEMP_CRITICAL_MSG \ 57 gettext("CRITICAL : HIGH TEMPERATURE DETECTED %d, %s") 58 #define HIGHTEMP_WARNING_MSG \ 59 gettext("WARNING : HIGH TEMPERATURE DETECTED %d, %s") 60 #define DEVICE_INSERTED_MSG gettext("Device %s inserted") 61 #define DEVICE_REMOVED_MSG gettext("Device %s removed") 62 #define DEVICE_FAILURE_MSG \ 63 gettext("CRITICAL: Device %s failure detected by sensor %s\n") 64 #define DEVICE_OK_MSG gettext("Device %s OK") 65 #define SECONDARY_FAN_FAIL_MSG gettext("Secondary fan failure, device %s") 66 #define KEYSWITCH_POS_READ_FAILED_MSG \ 67 gettext("Keyswitch position could not be determined") 68 #define KEYSWITCH_POS_CHANGED_MSG gettext("Keyswitch position changed to %s") 69 #define GET_PRESENCE_FAILED_MSG \ 70 gettext("Failed to get presence attribute, id = %s, errno = %d\n") 71 #define GET_SENSOR_FAILED_MSG \ 72 gettext("Failed to get sensor value, id = %s, errno = %d\n") 73 #define PS_OVER_CURRENT_MSG \ 74 gettext("WARNING: Power Supply overcurrent detected for %s\n") 75 #define SET_LED_FAILED_MSG \ 76 gettext("Failed to set LED state, id = %s, errno = %d\n") 77 #define SET_FANSPEED_FAILED_MSG \ 78 gettext("Failed to set fan speed, id = %s, errno = %d\n") 79 #define FAN_MISSING_MSG \ 80 gettext("WARNING: Fan missing, id = %s\n") 81 #define TEMP_SENSOR_FAULT \ 82 gettext("WARNING: Temperature Sensor %s returning faulty temp\n") 83 #define TEMP_OFFSET 17 84 85 static char *shutdown_string = "shutdown -y -g 60 -i 5 \"OVERTEMP condition\""; 86 87 static int cpus_online = 0; 88 89 typedef struct seg_desc { 90 int32_t segdesc; 91 int16_t segoffset; 92 int16_t seglength; 93 } seg_desc_t; 94 95 static int32_t threshold_names[] = { 96 PSVC_HW_LO_SHUT_ATTR, 97 PSVC_LO_SHUT_ATTR, 98 PSVC_LO_WARN_ATTR, 99 PSVC_NOT_USED, /* LOW MODE which is not used */ 100 PSVC_OPTIMAL_TEMP_ATTR, 101 PSVC_HI_WARN_ATTR, 102 PSVC_HI_SHUT_ATTR, 103 PSVC_HW_HI_SHUT_ATTR 104 }; 105 106 /* 107 * The I2C bus is noisy, and the state may be incorrectly reported as 108 * having changed. When the state changes, we attempt to confirm by 109 * retrying. If any retries indicate that the state has not changed, we 110 * assume the state change(s) were incorrect and the state has not changed. 111 * The following variables are used to store the tuneable values read in 112 * from the optional i2cparam.conf file for this shared object library. 113 */ 114 static int n_read_temp = PSVC_THRESHOLD_COUNTER; 115 static int n_retry_keyswitch = PSVC_NUM_OF_RETRIES; 116 static int retry_sleep_keyswitch = 1; 117 static int n_retry_hotplug = PSVC_NUM_OF_RETRIES; 118 static int retry_sleep_hotplug = 1; 119 static int n_retry_fan_hotplug = PSVC_NUM_OF_RETRIES; 120 static int retry_sleep_fan_hotplug = 1; 121 static int n_retry_fan_present = PSVC_NUM_OF_RETRIES; 122 static int retry_sleep_fan_present = 1; 123 124 typedef struct { 125 int *pvar; 126 char *texttag; 127 } i2c_noise_param_t; 128 129 static i2c_noise_param_t i2cparams_sun4u[] = { 130 &n_read_temp, "n_read_temp", 131 &n_retry_keyswitch, "n_retry_keyswitch", 132 &retry_sleep_keyswitch, "retry_sleep_keyswitch", 133 &n_retry_hotplug, "n_retry_hotplug", 134 &retry_sleep_hotplug, "retry_sleep_hotplug", 135 &n_retry_fan_hotplug, "n_retry_fan_hotplug", 136 &retry_sleep_fan_hotplug, "retry_sleep_fan_hotplug", 137 &n_retry_fan_present, "n_retry_fan_present", 138 &retry_sleep_fan_present, "retry_sleep_fan_present", 139 NULL, NULL 140 }; 141 142 #pragma init(i2cparams_sun4u_load) 143 144 static void 145 i2cparams_sun4u_debug(i2c_noise_param_t *pi2cparams, int usingDefaults) 146 { 147 char s[128]; 148 i2c_noise_param_t *p; 149 150 if (!usingDefaults) { 151 (void) strncpy(s, 152 "# Values from /usr/platform/sun4u/lib/i2cparam.conf\n", 153 sizeof (s) - 1); 154 syslog(LOG_WARNING, "%s", s); 155 } else { 156 /* no file - we're using the defaults */ 157 (void) strncpy(s, 158 "# No /usr/platform/sun4u/lib/i2cparam.conf file, using defaults\n", 159 sizeof (s) - 1); 160 } 161 (void) fputs(s, stdout); 162 p = pi2cparams; 163 while (p->pvar != NULL) { 164 (void) snprintf(s, sizeof (s), "%s %d\n", p->texttag, 165 *(p->pvar)); 166 if (!usingDefaults) 167 syslog(LOG_WARNING, "%s", s); 168 (void) fputs(s, stdout); 169 p++; 170 } 171 } 172 173 static void 174 i2cparams_sun4u_load(void) 175 { 176 FILE *fp; 177 char *filename = "/usr/platform/sun4u/lib/i2cparam.conf"; 178 char s[128]; 179 char var[128]; 180 int val; 181 i2c_noise_param_t *p; 182 183 /* read thru the i2cparam.conf file and set variables */ 184 if ((fp = fopen(filename, "r")) != NULL) { 185 while (fgets(s, sizeof (s), fp) != NULL) { 186 if (s[0] == '#') /* skip comment lines */ 187 continue; 188 /* try to find a string match and get the value */ 189 if (sscanf(s, "%127s %d", var, &val) != 2) 190 continue; 191 if (val < 1) 192 val = 1; /* clamp min value */ 193 p = &(i2cparams_sun4u[0]); 194 while (p->pvar != NULL) { 195 if (strncmp(p->texttag, var, sizeof (var)) == 196 0) { 197 *(p->pvar) = val; 198 break; 199 } 200 p++; 201 } 202 } 203 (void) fclose(fp); 204 } 205 /* output the values of the parameters */ 206 i2cparams_sun4u_debug(&(i2cparams_sun4u[0]), ((fp == NULL)? 1 : 0)); 207 } 208 209 210 int32_t 211 psvc_update_thresholds_0(psvc_opaque_t hdlp, char *id) 212 { 213 int32_t status = PSVC_SUCCESS; 214 fru_info_t fru_data; 215 char *fru, seg_name[2]; 216 int8_t seg_count, temp_array[8]; 217 int32_t match_count, i, j, seg_desc_start = 0x1806, temp_address; 218 int32_t seg_found, temp; 219 boolean_t present; 220 seg_desc_t segment; 221 222 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 223 if ((status != PSVC_SUCCESS) || (present != PSVC_PRESENT)) 224 return (status); 225 226 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &match_count, 227 PSVC_FRU); 228 if (status == PSVC_FAILURE) 229 return (status); 230 231 for (i = 0; i < match_count; i++) { 232 seg_found = 0; 233 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 234 &fru, PSVC_FRU, i); 235 if (status != PSVC_SUCCESS) 236 return (status); 237 238 fru_data.buf_start = 0x1805; 239 fru_data.buf = (char *)&seg_count; 240 fru_data.read_size = 1; 241 242 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 243 &fru_data); 244 if (status != PSVC_SUCCESS) { 245 return (status); 246 } 247 for (j = 0; (j < seg_count) && (!seg_found); j++) { 248 fru_data.buf_start = seg_desc_start; 249 fru_data.buf = seg_name; 250 fru_data.read_size = 2; 251 252 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 253 &fru_data); 254 255 seg_desc_start = seg_desc_start + 2; 256 fru_data.buf_start = seg_desc_start; 257 fru_data.buf = (char *)&segment; 258 fru_data.read_size = sizeof (seg_desc_t); 259 260 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 261 &fru_data); 262 if (status != PSVC_SUCCESS) { 263 syslog(LOG_ERR, 264 "Failed psvc_get_attr for FRU info\n"); 265 return (status); 266 } 267 seg_desc_start = seg_desc_start + sizeof (seg_desc_t); 268 if (memcmp(seg_name, "SC", 2) == 0) 269 seg_found = 1; 270 } 271 if (seg_found) { 272 temp_address = segment.segoffset + TEMP_OFFSET; 273 fru_data.buf_start = temp_address; 274 fru_data.buf = (char *)&temp_array; 275 fru_data.read_size = sizeof (temp_array); 276 status = psvc_get_attr(hdlp, fru, PSVC_FRU_INFO_ATTR, 277 &fru_data); 278 if (status != PSVC_SUCCESS) { 279 syslog(LOG_ERR, 280 "Failed psvc_get_attr for FRU info\n"); 281 return (status); 282 } else { 283 for (j = 0; j < sizeof (temp_array); j++) { 284 if (threshold_names[j] == PSVC_NOT_USED) 285 continue; 286 temp = temp_array[j]; 287 status = psvc_set_attr(hdlp, id, 288 threshold_names[j], &temp); 289 if (status != PSVC_SUCCESS) { 290 return (status); 291 } 292 } 293 } 294 } else { 295 syslog(LOG_ERR, "No FRU Information for %s" 296 " using default temperatures\n", id); 297 } 298 } 299 return (status); 300 } 301 302 #define MAX_TEMP_SENSORS 256 303 304 static int32_t 305 check_temp(psvc_opaque_t hdlp, char *id, int32_t silent) 306 { 307 int32_t lo_warn, hi_warn, lo_shut, hi_shut; 308 uint64_t features; 309 int32_t temp; 310 char previous_state[32]; 311 char led_state[32]; 312 char state[32]; 313 char fault[32]; 314 char label[32]; 315 boolean_t pr; 316 int32_t status = PSVC_SUCCESS; 317 int8_t fail = 0; 318 static int threshold_low_shut[MAX_TEMP_SENSORS] = {0}; 319 static int threshold_high_shut[MAX_TEMP_SENSORS] = {0}; 320 static int threshold_low_warn[MAX_TEMP_SENSORS] = {0}; 321 static int threshold_high_warn[MAX_TEMP_SENSORS] = {0}; 322 int32_t instance; 323 324 status = psvc_get_attr(hdlp, id, PSVC_INSTANCE_ATTR, &instance); 325 if (status != PSVC_SUCCESS) 326 return (status); 327 328 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &pr); 329 if ((status != PSVC_SUCCESS) || (pr != PSVC_PRESENT)) { 330 return (status); 331 } 332 333 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state); 334 if (status == PSVC_FAILURE) 335 return (status); 336 337 if ((strcmp(state, PSVC_HOTPLUGGED) == 0)) { 338 return (PSVC_SUCCESS); 339 } 340 341 status = psvc_get_attr(hdlp, id, PSVC_FEATURES_ATTR, &features); 342 if (status != PSVC_SUCCESS) 343 return (status); 344 345 status = psvc_get_attr(hdlp, id, PSVC_LO_WARN_ATTR, &lo_warn); 346 if (status != PSVC_SUCCESS) 347 return (status); 348 349 status = psvc_get_attr(hdlp, id, PSVC_LO_SHUT_ATTR, &lo_shut); 350 if (status != PSVC_SUCCESS) 351 return (status); 352 353 status = psvc_get_attr(hdlp, id, PSVC_HI_WARN_ATTR, &hi_warn); 354 if (status != PSVC_SUCCESS) 355 return (status); 356 357 status = psvc_get_attr(hdlp, id, PSVC_HI_SHUT_ATTR, &hi_shut); 358 if (status != PSVC_SUCCESS) 359 return (status); 360 361 status = psvc_get_attr(hdlp, id, PSVC_SENSOR_VALUE_ATTR, &temp); 362 if (status != PSVC_SUCCESS) { 363 return (status); 364 } 365 366 /* 367 * The following code is to check to see if the temp sensor is 368 * returning a faulty reading due to it either being bad or the 369 * CPU being powered off for some reason. Is so we will alert the user 370 * and just label the sensor bad but not the WHOLE CPU module. 371 */ 372 if ((temp == 127) && (strcmp(state, PSVC_ERROR) != 0)) { 373 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, PSVC_ERROR); 374 if (status != PSVC_SUCCESS) 375 return (status); 376 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, 377 PSVC_GEN_FAULT); 378 if (status != PSVC_SUCCESS) 379 return (status); 380 syslog(LOG_ERR, TEMP_SENSOR_FAULT, id); 381 return (status); 382 } 383 384 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 385 if (status != PSVC_SUCCESS) 386 return (status); 387 388 /* 389 * if any of the four temperature states (lo_shut, lo_warn, 390 * hi_shut, hi_warn) is detected we will not take an action 391 * until the number of similar back-to-back readings equals 392 * 'n_read_temp' (default is PSVC_THRESHOLD_COUNTER). 393 */ 394 if ((features & PSVC_LOW_SHUT) && temp < lo_shut) { 395 /* 396 * once we are in one state, clear all the 397 * counters for the other three states since 398 * back-to-back readings of these other three 399 * states could not happen anymore. 400 */ 401 threshold_low_warn[instance] = 0; 402 threshold_high_shut[instance] = 0; 403 threshold_high_warn[instance] = 0; 404 threshold_low_shut[instance]++; 405 if (threshold_low_shut[instance] == n_read_temp) { 406 threshold_low_shut[instance] = 0; 407 fail = 1; 408 strcpy(state, PSVC_ERROR); 409 strcpy(fault, PSVC_TEMP_LO_SHUT); 410 strcpy(led_state, PSVC_LED_ON); 411 if (silent == 0) 412 syslog(LOG_ERR, LOWTEMP_CRITICAL_MSG, 413 temp, label); 414 } else { /* Threshold for showing error not reached */ 415 return (PSVC_SUCCESS); 416 } 417 } else if ((features & PSVC_LOW_WARN) && temp < lo_warn) { 418 threshold_low_shut[instance] = 0; 419 threshold_high_shut[instance] = 0; 420 threshold_high_warn[instance] = 0; 421 threshold_low_warn[instance]++; 422 if (threshold_low_warn[instance] == n_read_temp) { 423 threshold_low_warn[instance] = 0; 424 fail = 1; 425 strcpy(state, PSVC_ERROR); 426 strcpy(fault, PSVC_TEMP_LO_WARN); 427 strcpy(led_state, PSVC_LED_ON); 428 if (silent == 0) 429 syslog(LOG_ERR, LOWTEMP_WARNING_MSG, 430 temp, label); 431 } else { /* Threshold for showing error not reached */ 432 return (PSVC_SUCCESS); 433 } 434 } else if ((features & PSVC_HIGH_SHUT) && temp > hi_shut) { 435 threshold_low_warn[instance] = 0; 436 threshold_low_shut[instance] = 0; 437 threshold_high_warn[instance] = 0; 438 threshold_high_shut[instance]++; 439 if (threshold_high_shut[instance] == n_read_temp) { 440 threshold_high_shut[instance] = 0; 441 fail = 1; 442 strcpy(state, PSVC_ERROR); 443 strcpy(fault, PSVC_TEMP_HI_SHUT); 444 strcpy(led_state, PSVC_LED_ON); 445 if (silent == 0) 446 syslog(LOG_ERR, HIGHTEMP_CRITICAL_MSG, 447 temp, label); 448 } else { /* Threshold for showing error not reached */ 449 return (PSVC_SUCCESS); 450 } 451 } else if ((features & PSVC_HIGH_WARN) && temp > hi_warn) { 452 threshold_low_warn[instance] = 0; 453 threshold_low_shut[instance] = 0; 454 threshold_high_shut[instance] = 0; 455 threshold_high_warn[instance]++; 456 if (threshold_high_warn[instance] == n_read_temp) { 457 threshold_high_warn[instance] = 0; 458 fail = 1; 459 strcpy(state, PSVC_ERROR); 460 strcpy(fault, PSVC_TEMP_HI_WARN); 461 strcpy(led_state, PSVC_LED_ON); 462 if (silent == 0) 463 syslog(LOG_ERR, HIGHTEMP_WARNING_MSG, 464 temp, label); 465 } else { /* Threshold for showing error not reached */ 466 return (PSVC_SUCCESS); 467 } 468 } 469 470 /* 471 * If we reached this point then that means that we are either 472 * okay, or we have showed error n_read_temp times. 473 */ 474 if (fail != 1) { 475 /* within limits */ 476 strcpy(state, PSVC_OK); 477 strcpy(fault, PSVC_NO_FAULT); 478 strcpy(led_state, PSVC_LED_OFF); 479 } 480 481 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 482 if (status != PSVC_SUCCESS) 483 return (status); 484 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 485 if (status != PSVC_SUCCESS) 486 return (status); 487 status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 488 previous_state); 489 if (status != PSVC_SUCCESS) 490 return (status); 491 492 if (strcmp(previous_state, state) != 0) { 493 char *led_id; 494 int32_t led_count; 495 int32_t i; 496 497 /* change state of fault LEDs */ 498 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &led_count, 499 PSVC_TS_OVERTEMP_LED); 500 for (i = 0; i < led_count; ++i) { 501 status = psvc_get_attr(hdlp, id, 502 PSVC_ASSOC_ID_ATTR, &led_id, 503 PSVC_TS_OVERTEMP_LED, i); 504 if (status == PSVC_FAILURE) 505 return (status); 506 status = psvc_set_attr(hdlp, led_id, 507 PSVC_LED_STATE_ATTR, led_state); 508 if (status == PSVC_FAILURE) 509 return (status); 510 } 511 } 512 513 return (PSVC_SUCCESS); 514 } 515 516 int32_t 517 psvc_check_temperature_policy_0(psvc_opaque_t hdlp, char *id) 518 { 519 return (check_temp(hdlp, id, 0)); 520 } 521 522 int32_t 523 psvc_check_temperature_silent_policy_0(psvc_opaque_t hdlp, char *id) 524 { 525 return (check_temp(hdlp, id, 1)); 526 } 527 528 int32_t 529 psvc_fan_enable_disable_policy_0(psvc_opaque_t hdlp, char *id) 530 { 531 char state[32], previous_state[32]; 532 char *backup_fan; 533 int32_t status = PSVC_SUCCESS; 534 uint64_t features; 535 char label[32]; 536 boolean_t presence; 537 boolean_t enable; 538 int retry; 539 540 status = psvc_get_attr(hdlp, id, PSVC_FEATURES_ATTR, &features); 541 if (status != PSVC_SUCCESS) 542 return (status); 543 544 retry = 0; 545 do { 546 if (retry) 547 (void) sleep(retry_sleep_fan_present); 548 549 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 550 if (status != PSVC_SUCCESS) 551 return (status); 552 retry++; 553 } while ((retry < n_retry_fan_present) && (presence == PSVC_ABSENT)); 554 555 if (presence == PSVC_ABSENT) { 556 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 557 if (status != PSVC_SUCCESS) 558 return (status); 559 560 status = psvc_get_attr(hdlp, id, PSVC_ENABLE_ATTR, &enable); 561 if (status != PSVC_SUCCESS) 562 return (status); 563 564 if (features & PSVC_DEV_PRIMARY) { 565 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 566 &backup_fan, PSVC_ALTERNATE, 0); 567 if (status != PSVC_SUCCESS) 568 return (status); 569 570 enable = PSVC_DISABLED; 571 status = psvc_set_attr(hdlp, id, PSVC_ENABLE_ATTR, 572 &enable); 573 if (status != PSVC_SUCCESS) 574 return (status); 575 576 enable = PSVC_ENABLED; 577 status = psvc_set_attr(hdlp, backup_fan, 578 PSVC_ENABLE_ATTR, &enable); 579 if (status != PSVC_SUCCESS) 580 return (status); 581 } else { 582 enable = PSVC_DISABLED; 583 status = psvc_set_attr(hdlp, id, PSVC_ENABLE_ATTR, 584 &enable); 585 if (status != PSVC_SUCCESS) 586 return (status); 587 } 588 return (PSVC_SUCCESS); 589 } 590 591 /* device was present */ 592 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, state); 593 if (status != PSVC_SUCCESS) 594 return (status); 595 596 status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, previous_state); 597 if (status != PSVC_SUCCESS) 598 return (status); 599 600 if (features & PSVC_DEV_PRIMARY) { 601 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 602 &backup_fan, PSVC_ALTERNATE, 0); 603 if (status != PSVC_SUCCESS) 604 return (status); 605 606 if (strcmp(state, PSVC_OK) == 0) { 607 enable = PSVC_ENABLED; 608 status = psvc_set_attr(hdlp, id, PSVC_ENABLE_ATTR, 609 &enable); 610 if (status != PSVC_SUCCESS) 611 return (status); 612 613 enable = PSVC_DISABLED; 614 status = psvc_set_attr(hdlp, backup_fan, 615 PSVC_ENABLE_ATTR, &enable); 616 if (status != PSVC_SUCCESS) 617 return (status); 618 } 619 if ((strcmp(state, PSVC_ERROR) == 0) && 620 (strcmp(previous_state, PSVC_ERROR) != 0)) { 621 enable = PSVC_DISABLED; 622 status = psvc_set_attr(hdlp, id, PSVC_ENABLE_ATTR, 623 &enable); 624 if (status != PSVC_SUCCESS) 625 return (status); 626 627 enable = PSVC_ENABLED; 628 status = psvc_set_attr(hdlp, backup_fan, 629 PSVC_ENABLE_ATTR, &enable); 630 if (status != PSVC_SUCCESS) 631 return (status); 632 } 633 } else { 634 if ((strcmp(state, PSVC_ERROR) == 0) && 635 (strcmp(previous_state, PSVC_ERROR) != 0)) { 636 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, 637 label); 638 if (status != PSVC_SUCCESS) 639 return (status); 640 syslog(LOG_ERR, SECONDARY_FAN_FAIL_MSG, label); 641 } 642 } 643 return (status); 644 } 645 646 /* 647 * psvc_switch_fan_onoff_policy_0 648 * Turn a fan on if it is enabled, turn it off if it is disabled. 649 */ 650 int32_t 651 psvc_switch_fan_onoff_policy_0(psvc_opaque_t hdlp, char *id) 652 { 653 boolean_t enable; 654 char *switchid; 655 char state[32]; 656 int32_t status = PSVC_SUCCESS; 657 658 status = psvc_get_attr(hdlp, id, PSVC_ENABLE_ATTR, &enable); 659 if (status != PSVC_SUCCESS) 660 return (status); 661 662 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &switchid, 663 PSVC_FAN_ONOFF_SENSOR, 0); 664 if (status != PSVC_SUCCESS) 665 return (status); 666 667 if (enable == PSVC_DISABLED) { 668 strcpy(state, PSVC_SWITCH_OFF); 669 } else { 670 strcpy(state, PSVC_SWITCH_ON); 671 } 672 673 status = psvc_set_attr(hdlp, switchid, PSVC_SWITCH_STATE_ATTR, state); 674 return (status); 675 } 676 677 static int32_t 678 check_cpu_temp_fault(psvc_opaque_t hdlp, char *cpu, int32_t cpu_count) 679 { 680 char *sensorid; 681 int32_t sensor_count; 682 int32_t status = PSVC_SUCCESS; 683 int32_t i; 684 uint64_t features; 685 char fault[32]; 686 687 status = psvc_get_attr(hdlp, cpu, PSVC_FEATURES_ATTR, &features); 688 if (status == PSVC_FAILURE) 689 return (status); 690 691 psvc_get_attr(hdlp, cpu, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 692 PSVC_DEV_TEMP_SENSOR); 693 for (i = 0; i < sensor_count; ++i) { 694 status = psvc_get_attr(hdlp, cpu, PSVC_ASSOC_ID_ATTR, 695 &sensorid, PSVC_DEV_TEMP_SENSOR, i); 696 if (status == PSVC_FAILURE) 697 return (status); 698 699 status = psvc_get_attr(hdlp, sensorid, PSVC_FAULTID_ATTR, 700 fault); 701 if (status == PSVC_FAILURE) 702 return (status); 703 704 if ((strcmp(fault, PSVC_TEMP_HI_SHUT) == 0) || 705 (strcmp(fault, PSVC_TEMP_LO_SHUT) == 0)) { 706 if (cpu_count == 1 || cpus_online == 1 || 707 !(features & PSVC_DEV_HOTPLUG)) { 708 system(shutdown_string); 709 } else { 710 /* FIX offline cpu */ 711 --cpus_online; 712 } 713 } 714 } 715 716 return (status); 717 } 718 719 int32_t 720 psvc_shutdown_policy_0(psvc_opaque_t hdlp, char *id) 721 { 722 int32_t cpu_count; 723 char *cpuid; 724 int32_t i; 725 boolean_t present; 726 int32_t status = PSVC_SUCCESS; 727 728 if (cpus_online == 0) { 729 /* obviously, zero isn't correct, count present cpu's */ 730 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &cpu_count, 731 PSVC_CPU); 732 for (i = 0; i < cpu_count; ++i) { 733 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 734 &cpuid, PSVC_CPU, i); 735 if (status == PSVC_FAILURE) 736 return (status); 737 738 status = psvc_get_attr(hdlp, cpuid, 739 PSVC_PRESENCE_ATTR, &present); 740 if (status == PSVC_FAILURE && present == PSVC_PRESENT) 741 return (status); 742 if (present == PSVC_PRESENT) 743 ++cpus_online; 744 } 745 } 746 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &cpu_count, 747 PSVC_CPU); 748 for (i = 0; i < cpu_count; ++i) { 749 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, &cpuid, 750 PSVC_CPU, i); 751 if (status == PSVC_FAILURE) 752 return (status); 753 status = check_cpu_temp_fault(hdlp, cpuid, cpu_count); 754 if (status == PSVC_FAILURE && errno != ENODEV) 755 return (status); 756 } 757 758 return (PSVC_SUCCESS); 759 } 760 761 /* 762 * psvc_keyswitch_position_policy_0 763 * Checks the state of the keyswitch sensors. 764 * If a keyswitch position sensor's state is on, the position 765 * of the key is written to syslog. If none of the sensors 766 * are on (keyswitch is not at one of the detents), a message is sent 767 * to syslog stating that the position is unknown. 768 */ 769 int32_t 770 psvc_keyswitch_position_policy_0(psvc_opaque_t hdlp, char *id) 771 { 772 char position[32]; 773 int32_t status = PSVC_SUCCESS; 774 static int error_reported = 0; 775 static char local_previous_position[32]; 776 static int32_t first_time = 1; 777 int retry; 778 779 if (first_time) { 780 first_time = 0; 781 status = psvc_get_attr(hdlp, id, PSVC_STATE_ATTR, 782 local_previous_position); 783 if (status != PSVC_SUCCESS) 784 return (status); 785 } 786 787 retry = 0; 788 do { 789 if (retry) 790 (void) sleep(retry_sleep_keyswitch); 791 792 status = psvc_get_attr(hdlp, id, PSVC_SWITCH_STATE_ATTR, 793 position); 794 if (status != PSVC_SUCCESS) 795 return (status); 796 797 if (strcmp(position, PSVC_ERROR) == 0) { 798 if ((errno == EINVAL) && (!(error_reported))) { 799 syslog(LOG_ERR, 800 KEYSWITCH_POS_READ_FAILED_MSG); 801 error_reported = 1; 802 return (PSVC_SUCCESS); 803 } 804 } 805 retry++; 806 } while ((retry < n_retry_keyswitch) && 807 (strcmp(position, local_previous_position) != 0)); 808 809 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, position); 810 if (status != PSVC_SUCCESS) 811 return (status); 812 813 if (strcmp(position, local_previous_position) != 0) { 814 error_reported = 0; 815 strcpy(local_previous_position, position); 816 syslog(LOG_ERR, KEYSWITCH_POS_CHANGED_MSG, position); 817 } 818 819 return (status); 820 } 821 822 int32_t 823 psvc_hotplug_notifier_policy_0(psvc_opaque_t hdlp, char *id) 824 { 825 boolean_t presence, previous_presence; 826 int32_t status = PSVC_SUCCESS; 827 char label[32]; 828 int retry; 829 830 status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, 831 &previous_presence); 832 if (status != PSVC_SUCCESS) 833 return (status); 834 835 retry = 0; 836 do { 837 if (retry) 838 (void) sleep(retry_sleep_hotplug); 839 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 840 if (status != PSVC_SUCCESS) 841 return (status); 842 retry++; 843 } while ((retry < n_retry_hotplug) && 844 (presence != previous_presence)); 845 846 847 if (presence != previous_presence) { 848 char parent_path[256]; 849 picl_nodehdl_t child_node; 850 851 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 852 if (status != PSVC_SUCCESS) 853 return (status); 854 855 /* return parent path and node for an object */ 856 psvcplugin_lookup(id, parent_path, &child_node); 857 858 if (presence == PSVC_PRESENT) { 859 char state[32], fault[32]; 860 picl_nodehdl_t parent_node; 861 862 syslog(LOG_ERR, DEVICE_INSERTED_MSG, label); 863 strcpy(state, PSVC_OK); 864 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 865 state); 866 if (status != PSVC_SUCCESS) 867 return (status); 868 strcpy(fault, PSVC_NO_FAULT); 869 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, 870 fault); 871 if (status != PSVC_SUCCESS) { 872 return (status); 873 } 874 875 status = ptree_get_node_by_path(parent_path, 876 &parent_node); 877 if (status != 0) 878 return (PSVC_FAILURE); 879 status = ptree_add_node(parent_node, child_node); 880 if (status != 0) 881 return (PSVC_FAILURE); 882 } else { 883 syslog(LOG_ERR, DEVICE_REMOVED_MSG, label); 884 885 ptree_delete_node(child_node); 886 887 } 888 } 889 890 status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence); 891 if (status != PSVC_SUCCESS) 892 return (status); 893 894 return (status); 895 } 896 897 int32_t 898 psvc_fan_hotplug_policy_0(psvc_opaque_t hdlp, char *id) 899 { 900 boolean_t presence, previous_presence; 901 int32_t status = PSVC_SUCCESS; 902 char label[32]; 903 int retry; 904 905 status = psvc_get_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, 906 &previous_presence); 907 if (status != PSVC_SUCCESS) 908 return (status); 909 910 retry = 0; 911 do { 912 if (retry) 913 (void) sleep(retry_sleep_fan_hotplug); 914 915 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 916 if (status != PSVC_SUCCESS) 917 return (status); 918 retry++; 919 } while ((retry < n_retry_fan_hotplug) && 920 (presence != previous_presence)); 921 922 923 if (presence != previous_presence) { 924 char parent_path[256]; 925 picl_nodehdl_t child_node; 926 927 status = psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, label); 928 if (status != PSVC_SUCCESS) 929 return (status); 930 931 /* return parent path and node for an object */ 932 psvcplugin_lookup(id, parent_path, &child_node); 933 934 if (presence == PSVC_PRESENT) { 935 char state[32], fault[32]; 936 char *slot_id; 937 char *led_id; 938 int32_t i, led_count; 939 char led_state[32]; 940 picl_nodehdl_t parent_node; 941 942 syslog(LOG_ERR, DEVICE_INSERTED_MSG, label); 943 944 strcpy(state, PSVC_OK); 945 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, 946 state); 947 if (status != PSVC_SUCCESS) 948 return (status); 949 strcpy(fault, PSVC_NO_FAULT); 950 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, 951 fault); 952 if (status != PSVC_SUCCESS) 953 return (status); 954 955 /* turn off fault LEDs */ 956 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 957 &led_count, PSVC_DEV_FAULT_LED); 958 strcpy(led_state, PSVC_LED_OFF); 959 for (i = 0; i < led_count; ++i) { 960 status = psvc_get_attr(hdlp, id, 961 PSVC_ASSOC_ID_ATTR, &led_id, 962 PSVC_DEV_FAULT_LED, i); 963 if (status == PSVC_FAILURE) 964 return (status); 965 status = psvc_set_attr(hdlp, led_id, 966 PSVC_LED_STATE_ATTR, led_state); 967 if (status == PSVC_FAILURE) 968 return (status); 969 } 970 971 /* turn off OK to remove LEDs */ 972 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 973 &slot_id, PSVC_PARENT, 0); 974 if (status != PSVC_SUCCESS) 975 return (status); 976 977 psvc_get_attr(hdlp, slot_id, PSVC_ASSOC_MATCHES_ATTR, 978 &led_count, PSVC_SLOT_REMOVE_LED); 979 strcpy(led_state, PSVC_LED_OFF); 980 for (i = 0; i < led_count; ++i) { 981 status = psvc_get_attr(hdlp, slot_id, 982 PSVC_ASSOC_ID_ATTR, &led_id, 983 PSVC_SLOT_REMOVE_LED, i); 984 if (status == PSVC_FAILURE) 985 return (status); 986 987 status = psvc_set_attr(hdlp, led_id, 988 PSVC_LED_STATE_ATTR, led_state); 989 if (status == PSVC_FAILURE) 990 return (status); 991 } 992 993 ptree_get_node_by_path(parent_path, &parent_node); 994 ptree_add_node(parent_node, child_node); 995 } else { 996 syslog(LOG_ERR, DEVICE_REMOVED_MSG, label); 997 ptree_delete_node(child_node); 998 } 999 } 1000 1001 status = psvc_set_attr(hdlp, id, PSVC_PREV_PRESENCE_ATTR, &presence); 1002 if (status != PSVC_SUCCESS) 1003 return (status); 1004 1005 return (status); 1006 } 1007 1008 int32_t 1009 psvc_init_led_policy_0(psvc_opaque_t hdlp, char *id) 1010 { 1011 int32_t status; 1012 1013 status = psvc_set_attr(hdlp, id, PSVC_LED_STATE_ATTR, PSVC_LED_OFF); 1014 return (status); 1015 } 1016 1017 int32_t 1018 psvc_init_state_policy_0(psvc_opaque_t hdlp, char *id) 1019 { 1020 int32_t status; 1021 1022 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, PSVC_OK); 1023 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, PSVC_NO_FAULT); 1024 return (status); 1025 } 1026 1027 int32_t 1028 psvc_ps_overcurrent_check_policy_0(psvc_opaque_t hdlp, char *power_supply_id) 1029 { 1030 int32_t status = PSVC_SUCCESS; 1031 boolean_t present; 1032 char *sensor_id; 1033 int32_t sensor_count; 1034 int32_t i; 1035 int32_t amps, hi_warn; 1036 1037 status = psvc_get_attr(hdlp, power_supply_id, PSVC_PRESENCE_ATTR, 1038 &present); 1039 if (status == PSVC_FAILURE) { 1040 syslog(LOG_ERR, GET_PRESENCE_FAILED_MSG, power_supply_id, 1041 errno); 1042 return (status); 1043 } 1044 1045 if (present == PSVC_ABSENT) { 1046 errno = ENODEV; 1047 return (PSVC_FAILURE); 1048 } 1049 1050 psvc_get_attr(hdlp, power_supply_id, PSVC_ASSOC_MATCHES_ATTR, 1051 &sensor_count, PSVC_PS_I_SENSOR); 1052 for (i = 0; i < sensor_count; ++i) { 1053 status = psvc_get_attr(hdlp, power_supply_id, 1054 PSVC_ASSOC_ID_ATTR, &sensor_id, PSVC_PS_I_SENSOR, i); 1055 if (status != PSVC_SUCCESS) 1056 return (status); 1057 1058 status = psvc_get_attr(hdlp, sensor_id, PSVC_HI_WARN_ATTR, 1059 &hi_warn); 1060 if (status != PSVC_SUCCESS) 1061 return (status); 1062 1063 status = psvc_get_attr(hdlp, sensor_id, 1064 PSVC_SENSOR_VALUE_ATTR, &s); 1065 if (status != PSVC_SUCCESS) { 1066 syslog(LOG_ERR, GET_SENSOR_FAILED_MSG, sensor_id, 1067 errno); 1068 return (status); 1069 } 1070 1071 if (amps >= hi_warn) { 1072 char label[32]; 1073 1074 status = psvc_get_attr(hdlp, power_supply_id, 1075 PSVC_LABEL_ATTR, &label); 1076 if (status != PSVC_SUCCESS) 1077 return (status); 1078 1079 syslog(LOG_ERR, PS_OVER_CURRENT_MSG, label); 1080 } 1081 } 1082 1083 return (PSVC_SUCCESS); 1084 1085 } 1086 1087 int32_t 1088 psvc_device_fail_notifier_policy_0(psvc_opaque_t hdlp, char *id) 1089 { 1090 int32_t led_count, sensor_count; 1091 char *led_id, *sensor_id; 1092 int i; 1093 char state[32], fault[32], previous_state[32]; 1094 char led_state[32]; 1095 int32_t status = PSVC_SUCCESS; 1096 boolean_t present; 1097 1098 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &present); 1099 if (status == PSVC_FAILURE) 1100 return (status); 1101 1102 if (present == PSVC_ABSENT) { 1103 errno = ENODEV; 1104 return (PSVC_FAILURE); 1105 } 1106 1107 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 1108 PSVC_DEV_FAULT_SENSOR); 1109 for (i = 0; i < sensor_count; ++i) { 1110 status = psvc_get_attr(hdlp, id, PSVC_ASSOC_ID_ATTR, 1111 &sensor_id, PSVC_DEV_FAULT_SENSOR, i); 1112 if (status != PSVC_SUCCESS) 1113 return (status); 1114 1115 status = psvc_get_attr(hdlp, sensor_id, 1116 PSVC_SWITCH_STATE_ATTR, state); 1117 if (status != PSVC_SUCCESS) 1118 return (status); 1119 1120 if (strcmp(state, PSVC_SWITCH_ON) == 0) { 1121 strcpy(state, PSVC_ERROR); 1122 strcpy(fault, PSVC_GEN_FAULT); 1123 } else { 1124 strcpy(state, PSVC_OK); 1125 strcpy(fault, PSVC_NO_FAULT); 1126 } 1127 1128 status = psvc_set_attr(hdlp, id, PSVC_STATE_ATTR, state); 1129 if (status != PSVC_SUCCESS) 1130 return (status); 1131 status = psvc_set_attr(hdlp, id, PSVC_FAULTID_ATTR, fault); 1132 if (status != PSVC_SUCCESS) 1133 return (status); 1134 status = psvc_get_attr(hdlp, id, PSVC_PREV_STATE_ATTR, 1135 previous_state); 1136 if (status != PSVC_SUCCESS) 1137 return (status); 1138 1139 if (strcmp(state, previous_state) != 0) { 1140 char sensor_label[32]; 1141 char dev_label[32]; 1142 int32_t j; 1143 1144 psvc_get_attr(hdlp, id, PSVC_LABEL_ATTR, dev_label); 1145 psvc_get_attr(hdlp, sensor_id, PSVC_LABEL_ATTR, 1146 sensor_label); 1147 1148 if (strcmp(state, PSVC_ERROR) == 0) { 1149 syslog(LOG_ERR, DEVICE_FAILURE_MSG, dev_label, 1150 sensor_label); 1151 strcpy(led_state, PSVC_LED_ON); 1152 } else { 1153 syslog(LOG_ERR, DEVICE_OK_MSG, dev_label); 1154 strcpy(led_state, PSVC_LED_OFF); 1155 } 1156 1157 psvc_get_attr(hdlp, id, PSVC_ASSOC_MATCHES_ATTR, 1158 &led_count, PSVC_DEV_FAULT_LED); 1159 for (j = 0; j < led_count; j++) { 1160 status = psvc_get_attr(hdlp, id, 1161 PSVC_ASSOC_ID_ATTR, &led_id, 1162 PSVC_DEV_FAULT_LED, j); 1163 if (status != PSVC_SUCCESS) 1164 return (status); 1165 status = psvc_set_attr(hdlp, led_id, 1166 PSVC_LED_STATE_ATTR, led_state); 1167 if (status != PSVC_SUCCESS) { 1168 syslog(LOG_ERR, SET_LED_FAILED_MSG, 1169 led_id, errno); 1170 return (status); 1171 } 1172 } 1173 } 1174 } 1175 1176 return (PSVC_SUCCESS); 1177 } 1178 1179 static float 1180 get_filtered_error(float *last_errors, int current_error) 1181 { 1182 float error; 1183 float adder; 1184 int i = 0; 1185 1186 adder = last_errors[0]; 1187 for (i = 1; i < PSVC_MAXERRORS; i++) { 1188 adder = adder + last_errors[i]; 1189 } 1190 adder = adder + current_error; 1191 error = adder/(PSVC_MAXERRORS+1); 1192 1193 return (error); 1194 } 1195 1196 static int32_t 1197 change_cpu_fans(psvc_opaque_t hdlp, char *fan_id, int32_t fan_speed) 1198 { 1199 int err = PSVC_SUCCESS; 1200 int i; 1201 int32_t control_count; 1202 char *control_id; 1203 int32_t old_fan_speed; 1204 1205 psvc_get_attr(hdlp, fan_id, PSVC_ASSOC_MATCHES_ATTR, &control_count, 1206 PSVC_FAN_DRIVE_CONTROL); 1207 if (control_count == 0) 1208 return (PSVC_SUCCESS); 1209 1210 err = psvc_get_attr(hdlp, fan_id, PSVC_ASSOC_ID_ATTR, &control_id, 1211 PSVC_FAN_DRIVE_CONTROL, 0); 1212 if (err != PSVC_SUCCESS) 1213 return (err); 1214 1215 /* 1216 * this call will return PSVC_FAILURE on the first pass, 1217 * because no value has been set. 1218 */ 1219 err = psvc_get_attr(hdlp, control_id, PSVC_CONTROL_VALUE_ATTR, 1220 &old_fan_speed); 1221 if (err == PSVC_SUCCESS && old_fan_speed == fan_speed) 1222 return (PSVC_SUCCESS); 1223 1224 for (i = 0; i < control_count; i++) { 1225 err = psvc_get_attr(hdlp, fan_id, PSVC_ASSOC_ID_ATTR, 1226 &control_id, PSVC_FAN_DRIVE_CONTROL, i); 1227 if (err != PSVC_SUCCESS) 1228 return (err); 1229 1230 err = psvc_set_attr(hdlp, control_id, PSVC_CONTROL_VALUE_ATTR, 1231 &fan_speed); 1232 if (err == PSVC_FAILURE) { 1233 syslog(LOG_ERR, SET_FANSPEED_FAILED_MSG, control_id, 1234 errno); 1235 return (err); 1236 } 1237 } 1238 return (err); 1239 } 1240 1241 static int32_t 1242 device_temp_check(psvc_opaque_t hdlp, char *fan_id, int32_t *hot_device) 1243 { 1244 int i; 1245 int32_t err = PSVC_SUCCESS; 1246 char *sensor_id; 1247 int32_t sensor_count; 1248 int32_t temp; 1249 1250 *hot_device = 0; 1251 1252 psvc_get_attr(hdlp, fan_id, PSVC_ASSOC_MATCHES_ATTR, &sensor_count, 1253 PSVC_DEV_TEMP_SENSOR); 1254 for (i = 0; i < sensor_count; i++) { 1255 err = psvc_get_attr(hdlp, fan_id, PSVC_ASSOC_ID_ATTR, 1256 &sensor_id, PSVC_DEV_TEMP_SENSOR, i); 1257 if (err == PSVC_FAILURE) 1258 return (err); 1259 err = psvc_get_attr(hdlp, sensor_id, PSVC_SENSOR_VALUE_ATTR, 1260 &temp); 1261 if (err == PSVC_FAILURE) { 1262 if (errno == ENODEV) { 1263 temp = 0; 1264 } else { 1265 syslog(LOG_ERR, GET_SENSOR_FAILED_MSG, 1266 sensor_id, errno); 1267 return (err); 1268 } 1269 } 1270 1271 if (*hot_device < temp) 1272 *hot_device = temp; 1273 } 1274 return (PSVC_SUCCESS); 1275 } 1276 1277 int32_t 1278 psvc_fan_control_policy_0(psvc_opaque_t hdlp, char *fan_id) 1279 { 1280 boolean_t is_enabled; 1281 int32_t err = PSVC_SUCCESS; 1282 int16_t setpoint, hysteresis, loopgain, loopbias; 1283 int current_error; /* Holds current error */ 1284 /* Signal before signaling */ 1285 float filtered_error; /* Holds the filtered error signal */ 1286 int ampout; /* output of loop amplifier */ 1287 int hot_device; 1288 1289 int16_t error_number; 1290 float last_errors[PSVC_MAXERRORS]; /* Holds the filtered error */ 1291 /* from the last n iterations */ 1292 1293 psvc_get_attr(hdlp, fan_id, PSVC_ENABLE_ATTR, &is_enabled); 1294 if (is_enabled == PSVC_DISABLED) 1295 return (PSVC_SUCCESS); 1296 1297 err = psvc_get_attr(hdlp, fan_id, PSVC_SETPOINT_ATTR, &setpoint); 1298 if (err != PSVC_SUCCESS) 1299 return (err); 1300 1301 err = psvc_get_attr(hdlp, fan_id, PSVC_HYSTERESIS_ATTR, 1302 &hysteresis); 1303 if (err != PSVC_SUCCESS) 1304 return (err); 1305 1306 err = psvc_get_attr(hdlp, fan_id, PSVC_LOOPGAIN_ATTR, &loopgain); 1307 if (err != PSVC_SUCCESS) 1308 return (err); 1309 1310 err = psvc_get_attr(hdlp, fan_id, PSVC_LOOPBIAS_ATTR, &loopbias); 1311 if (err != PSVC_SUCCESS) 1312 return (err); 1313 1314 err = psvc_get_attr(hdlp, fan_id, PSVC_TEMP_DIFFERENTIAL_ATTR, 1315 last_errors); 1316 if (err != PSVC_SUCCESS) 1317 return (err); 1318 1319 err = psvc_get_attr(hdlp, fan_id, PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR, 1320 &error_number); 1321 if (err != PSVC_SUCCESS) 1322 return (err); 1323 1324 err = device_temp_check(hdlp, fan_id, &hot_device); 1325 if (err != PSVC_SUCCESS) { 1326 printf("psvc_fan_control failure in device_temp_check\n"); 1327 return (err); 1328 } 1329 current_error = setpoint - hot_device; 1330 filtered_error = get_filtered_error(last_errors, current_error); 1331 if (filtered_error <= 0 || filtered_error > hysteresis) { 1332 ampout = (int)((filtered_error * loopgain) + loopbias); 1333 if (ampout < 0) 1334 ampout = 0; 1335 if (ampout > 1023) 1336 ampout = 1023; 1337 err = change_cpu_fans(hdlp, fan_id, ampout); 1338 if (err != PSVC_SUCCESS) 1339 return (err); 1340 } 1341 last_errors[error_number++] = current_error; 1342 if (error_number == PSVC_MAXERRORS) 1343 error_number = 0; 1344 1345 err = psvc_set_attr(hdlp, fan_id, PSVC_TEMP_DIFFERENTIAL_ATTR, 1346 last_errors); 1347 if (err != PSVC_SUCCESS) 1348 return (err); 1349 1350 err = psvc_set_attr(hdlp, fan_id, PSVC_TEMP_DIFFERENTIAL_INDEX_ATTR, 1351 &error_number); 1352 if (err != PSVC_SUCCESS) 1353 return (err); 1354 1355 return (PSVC_SUCCESS); 1356 } 1357 1358 int32_t 1359 psvc_fan_present_policy_0(psvc_opaque_t hdlp, char *id) 1360 { 1361 int32_t status = PSVC_SUCCESS; 1362 boolean_t presence; 1363 int fd; 1364 FILE *fp; 1365 int retry; 1366 1367 retry = 0; 1368 do { 1369 if (retry) 1370 (void) sleep(retry_sleep_fan_present); 1371 1372 status = psvc_get_attr(hdlp, id, PSVC_PRESENCE_ATTR, &presence); 1373 if (status != PSVC_SUCCESS) 1374 return (status); 1375 retry++; 1376 } while ((retry < n_retry_fan_present) && (presence == PSVC_ABSENT)); 1377 1378 if (presence == PSVC_ABSENT) { 1379 /* 1380 * We make this open, write, close, call because picld 1381 * starts in rcS.d while print services does not start 1382 * until later (either rc2.d or rc3.d) 1383 */ 1384 fd = open("/dev/console", O_WRONLY | O_NOCTTY); 1385 if (fd != -1) { 1386 fp = fdopen(fd, "w+"); 1387 if (fp != NULL) { 1388 fprintf(fp, FAN_MISSING_MSG, id); 1389 fclose(fp); 1390 } 1391 close(fd); 1392 } 1393 syslog(LOG_ERR, FAN_MISSING_MSG, id); 1394 } 1395 return (status); 1396 } 1397