summaryrefslogtreecommitdiff
path: root/usr/src/cmd/power/powerd.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/power/powerd.c')
-rw-r--r--usr/src/cmd/power/powerd.c172
1 files changed, 126 insertions, 46 deletions
diff --git a/usr/src/cmd/power/powerd.c b/usr/src/cmd/power/powerd.c
index 19e137ce02..a559041d0a 100644
--- a/usr/src/cmd/power/powerd.c
+++ b/usr/src/cmd/power/powerd.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -53,6 +53,7 @@
#include <sys/stropts.h> /* for INFTIM */
#include <sys/pbio.h>
#include <sys/cpr.h>
+#include <sys/srn.h>
#include <stdarg.h>
#include "powerd.h"
@@ -73,6 +74,7 @@ extern int last_nfs_activity(hrtime_t *, int);
#define TOD "/dev/tod"
#define PROM "/dev/openprom"
#define PB "/dev/power_button"
+#define SRN "/dev/srn"
#define LOGFILE "./powerd.log"
#define PBM_THREAD 0
@@ -108,9 +110,7 @@ static int autoshutdown_en;
static int do_idlecheck;
static int got_sighup;
static int estar_v2_prop;
-#ifdef sparc
static int estar_v3_prop;
-#endif
static int log_power_cycles_error = 0;
static int log_system_board_date_error = 0;
static int log_no_autoshutdown_warning = 0;
@@ -126,6 +126,11 @@ static char *power_button_cmd[] = {
"-h", "-d", ":0", NULL
};
+static char *autoS3_cmd[] = {
+ "/usr/openwin/bin/sys-suspend",
+ "-n", "-d", ":0", NULL
+};
+
static char pidpath[] = PIDPATH;
static char scratch[PATH_MAX];
static char *prog;
@@ -148,11 +153,10 @@ static int open_pidfile(char *);
static int write_pidfile(int, pid_t);
static int read_cpr_config(void);
static void system_activity_monitor(void);
-#ifdef sparc
+static void autos3_monitor(void);
static void do_attach(void);
static void *attach_devices(void *);
-#endif
-
+static int powerd_debug;
/* PRINTFLIKE1 */
static void
@@ -205,8 +209,11 @@ main(int argc, char *argv[])
* Process options
*/
broadcast = 1;
- while ((c = getopt(argc, argv, "n")) != EOF) {
+ while ((c = getopt(argc, argv, "nd")) != EOF) {
switch (c) {
+ case 'd':
+ powerd_debug = 1;
+ break;
case 'n':
broadcast = 0;
break;
@@ -230,7 +237,7 @@ main(int argc, char *argv[])
*/
if (mutex_init(&poweroff_mutex, USYNC_THREAD, NULL) != 0) {
(void) fprintf(stderr,
- "%s: Unable to initialize mutex lock\n", prog);
+ "%s: Unable to initialize mutex lock\n", prog);
exit(EXIT_FAILURE);
}
@@ -296,6 +303,8 @@ main(int argc, char *argv[])
* thread to monitor the power button.
*/
if ((pb_fd = open(PB, O_RDONLY)) != -1) {
+ if (powerd_debug)
+ logerror("powerd starting power button monitor.");
if (thr_create(NULL, NULL,
(void *(*)(void *))power_button_monitor, NULL,
THR_DAEMON, NULL) != 0) {
@@ -303,14 +312,14 @@ main(int argc, char *argv[])
}
}
-#ifdef sparc
do_attach();
-#endif
/*
* Create a new thread to monitor system activity and suspend
* system if idle.
*/
+ if (powerd_debug)
+ logerror("powerd starting system activity monitor.");
if (thr_create(NULL, NULL,
(void *(*)(void *))system_activity_monitor, NULL,
THR_DAEMON, NULL) != 0) {
@@ -318,6 +327,16 @@ main(int argc, char *argv[])
}
/*
+ * Create a new thread to handle autos3 trigger
+ */
+ if (powerd_debug)
+ logerror("powerd starting autos3 monitor.");
+ if (thr_create(NULL, NULL,
+ (void *(*)(void *))autos3_monitor, NULL, THR_DAEMON, NULL) != 0) {
+ logerror("Unable to create thread to monitor autos3 activity.");
+ }
+
+ /*
* Block until we receive an explicit terminate signal
*/
(void) sigsuspend(&sigmask);
@@ -370,6 +389,68 @@ system_activity_monitor(void)
} while (errno == EINTR);
}
+static void
+autos3_monitor(void)
+{
+ struct pollfd poll_fd;
+ srn_event_info_t srn_event; /* contains suspend type */
+ int fd, ret;
+
+ fd = open(SRN, O_RDWR|O_EXCL|O_NDELAY);
+ if (fd == -1) {
+ logerror("Unable to open %s: %s", SRN, strerror(errno));
+ thr_exit((void *) errno);
+ }
+ logerror("Able to open %s", SRN);
+
+ /*
+ * Tell device we want the special sauce
+ */
+ ret = ioctl(fd, SRN_IOC_AUTOSX, NULL);
+ if (ret == -1) {
+ logerror("Ioctl SRN_IOC_AUTOSX failed: %s", strerror(errno));
+ close(fd);
+ thr_exit((void *) errno);
+ }
+ poll_fd.fd = fd;
+ /*CONSTCOND*/
+ while (1) {
+ poll_fd.revents = 0;
+ poll_fd.events = POLLIN;
+ if (poll(&poll_fd, 1, -1) < 0) {
+ switch (errno) {
+ case EINTR:
+ case EAGAIN:
+ continue;
+ default:
+ logerror("Poll error: %s", strerror(errno));
+ close(fd);
+ thr_exit((void *) errno);
+ }
+ }
+
+ ret = ioctl(fd, SRN_IOC_NEXTEVENT, &srn_event);
+ if (ret == -1) {
+ logerror("ioctl error: %s", strerror(errno));
+ close(fd);
+ thr_exit((void *) errno);
+ }
+ switch (srn_event.ae_type) {
+ case 3: /* S3 */
+ if (powerd_debug)
+ logerror("ioctl returns type: %d",
+ srn_event.ae_type);
+ break;
+ default:
+ logerror("Unsupported target state %d",
+ srn_event.ae_type);
+ continue;
+ }
+ (void) poweroff("AutoS3", autoS3_cmd);
+ continue;
+ }
+}
+
static int
read_cpr_config(void)
{
@@ -482,7 +563,7 @@ work_handler(int sig)
} else if (strcmp(asinfo.as_behavior, "default") == 0) {
info->pd_autoshutdown = estar_v2_prop;
} else if (strcmp(asinfo.as_behavior, "shutdown") == 0 ||
- strcmp(asinfo.as_behavior, "autowakeup") == 0) {
+ strcmp(asinfo.as_behavior, "autowakeup") == 0) {
info->pd_autoshutdown = asinfo.is_cpr_capable;
} else {
logerror("autoshutdown behavior \"%s\" unrecognized.",
@@ -500,14 +581,15 @@ work_handler(int sig)
(strcmp(asinfo.as_behavior, "autowakeup") == 0) ? 1 : 0;
}
autoshutdown_en = (asinfo.as_idle >= 0 && info->pd_autoshutdown)
- ? 1 : 0;
+ ? 1 : 0;
#ifdef DEBUG
(void) fprintf(stderr, "autoshutdown_en = %d, as_idle = %d, "
- "pd_autoresume = %d\n",
- autoshutdown_en, asinfo.as_idle, info->pd_autoresume);
+ "pd_autoresume = %d\n",
+ autoshutdown_en, asinfo.as_idle, info->pd_autoresume);
+
(void) fprintf(stderr, " pd_start_time=%d, pd_finish_time=%d\n",
- info->pd_start_time, info->pd_finish_time);
+ info->pd_start_time, info->pd_finish_time);
#endif
got_sighup = 1;
@@ -574,11 +656,10 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
start_calc = 1;
time_since_last_resume = time(NULL) - last_resume;
next_time = info->pd_idle_time * 60 -
- MIN(least_idle, time_since_last_resume);
+ MIN(least_idle, time_since_last_resume);
#ifdef DEBUG
- fprintf(stderr, " check_shutdown: next_time=%d\n",
- next_time);
+ fprintf(stderr, " check_shutdown: next_time=%d\n", next_time);
#endif
/*
@@ -591,7 +672,7 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
start_calc = 1;
time_since_last_resume = time(NULL) - last_resume;
next_time = info->pd_idle_time * 60 -
- MIN(least_idle, time_since_last_resume);
+ MIN(least_idle, time_since_last_resume);
}
/*
@@ -602,8 +683,8 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
got_sighup = 0;
idlecheck_time = run_idlecheck();
next_time = info->pd_idle_time * 60 -
- MIN(idlecheck_time, MIN(least_idle,
- time_since_last_resume));
+ MIN(idlecheck_time, MIN(least_idle,
+ time_since_last_resume));
/*
* If we have caught SIGTHAW or SIGHUP, need to
* recalculate.
@@ -613,10 +694,10 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
got_sighup = 0;
idlecheck_time = run_idlecheck();
time_since_last_resume = time(NULL) -
- last_resume;
+ last_resume;
next_time = info->pd_idle_time * 60 -
- MIN(idlecheck_time, MIN(least_idle,
- time_since_last_resume));
+ MIN(idlecheck_time, MIN(least_idle,
+ time_since_last_resume));
}
}
@@ -631,7 +712,7 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
tod_fd = open(TOD, O_RDWR);
if (info->pd_autoresume && tod_fd != -1) {
wakeup_time = (*now < f) ? f :
- (f + DAYS_TO_SECS);
+ (f + DAYS_TO_SECS);
/*
* A software fix for hardware
* bug 1217415.
@@ -645,10 +726,9 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
return;
}
if (ioctl(tod_fd, TOD_SET_ALARM,
- &wakeup_time) == -1) {
- logerror("Unable to program "
- "TOD alarm for "
- "autowakeup.");
+ &wakeup_time) == -1) {
+ logerror("Unable to program TOD"
+ " alarm for autowakeup.");
close(tod_fd);
return;
}
@@ -659,7 +739,7 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
if (info->pd_autoresume && tod_fd != -1) {
if (ioctl(tod_fd, TOD_CLEAR_ALARM,
- NULL) == -1)
+ NULL) == -1)
logerror("Unable to clear "
"alarm in TOD device.");
close(tod_fd);
@@ -668,8 +748,8 @@ check_shutdown(time_t *now, hrtime_t *hr_now)
(void) time(now);
/* wait at least 5 mins */
shutdown_time = *now +
- ((info->pd_idle_time * 60) > 300 ?
- (info->pd_idle_time * 60) : 300);
+ ((info->pd_idle_time * 60) > 300 ?
+ (info->pd_idle_time * 60) : 300);
} else {
/* wait 5 mins */
shutdown_time = *now + 300;
@@ -698,8 +778,8 @@ is_ok2shutdown(time_t *now)
/* CONSTCOND */
while (1) {
if ((prom_fd = open(PROM, O_RDWR)) == -1 &&
- (errno == EAGAIN))
- continue;
+ (errno == EAGAIN))
+ continue;
break;
}
@@ -760,15 +840,14 @@ is_ok2shutdown(time_t *now)
* 7-year life span instead of (lifetime - date free_cycles ended).
*/
scaled_cycles = (int)(((float)life_passed / (float)LIFETIME_SECS) *
- (power_cycle_limit - free_cycles));
+ (power_cycle_limit - free_cycles));
if (no_power_cycles)
goto ckdone;
#ifdef DEBUG
(void) fprintf(stderr, "Actual power_cycles = %d\t"
- "Scaled power_cycles = %d\n",
- power_cycles, scaled_cycles);
+ "Scaled power_cycles = %d\n", power_cycles, scaled_cycles);
#endif
if (power_cycles > scaled_cycles) {
if (log_no_autoshutdown_warning == 0) {
@@ -807,13 +886,13 @@ check_idleness(time_t *now, hrtime_t *hr_now)
#ifdef DEBUG
(void) fprintf(stderr, "Idle ttychars for %d secs.\n",
- info->pd_ttychars_idle);
+ info->pd_ttychars_idle);
(void) fprintf(stderr, "Idle loadaverage for %d secs.\n",
- info->pd_loadaverage_idle);
+ info->pd_loadaverage_idle);
(void) fprintf(stderr, "Idle diskreads for %d secs.\n",
- info->pd_diskreads_idle);
+ info->pd_diskreads_idle);
(void) fprintf(stderr, "Idle nfsreqs for %d secs.\n",
- info->pd_nfsreqs_idle);
+ info->pd_nfsreqs_idle);
#endif
checkidle_time = *now + IDLECHK_INTERVAL;
@@ -848,7 +927,8 @@ run_idlecheck()
/*
* Reap any child process which has been left over.
*/
- while (waitpid((pid_t)-1, &status, WNOHANG) > 0);
+ while (waitpid((pid_t)-1, &status, WNOHANG) > 0)
+ ;
/*
* Execute the user's idlecheck script and set variable PM_IDLETIME.
@@ -856,7 +936,7 @@ run_idlecheck()
*/
if ((child = fork1()) == 0) {
(void) sprintf(pm_variable, "PM_IDLETIME=%d",
- info->pd_idle_time);
+ info->pd_idle_time);
(void) putenv(pm_variable);
cp = strrchr(asinfo.idlecheck_path, '/');
if (cp == NULL)
@@ -1136,7 +1216,6 @@ power_button_monitor(void *arg)
}
}
-#ifdef sparc
static void
do_attach(void)
{
@@ -1151,6 +1230,8 @@ do_attach(void)
estar_v3_prop = asinfo.is_autopm_default;
if ((strcmp(asinfo.apm_behavior, "enable") == 0) ||
(estar_v3_prop && strcmp(asinfo.apm_behavior, "default") == 0)) {
+ if (powerd_debug)
+ logerror("powerd starting device attach thread.");
if (thr_create(NULL, NULL, attach_devices, NULL,
THR_DAEMON, NULL) != 0) {
logerror("Unable to create thread to attach devices.");
@@ -1179,7 +1260,6 @@ attach_devices(void *arg)
return (NULL);
}
-#endif
/*
@@ -1199,7 +1279,7 @@ open_pidfile(char *me)
const char *e3 = "%s: Cannot open /proc for pid %ld: ";
const char *e4 = "%s: Cannot read /proc for pid %ld: ";
const char *e5 = "%s: Another instance (pid %ld) is trying to exit"
- "and may be hung. Please contact sysadmin.\n";
+ "and may be hung. Please contact sysadmin.\n";
const char *e6 = "%s: Another daemon is running\n";
const char *e7 = "%s: Cannot create pid file: ";