summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormh27603 <none@none>2006-11-01 12:29:40 -0800
committermh27603 <none@none>2006-11-01 12:29:40 -0800
commitc42872d4489d6f0fbccfabe2a62f3c976ee1e5d6 (patch)
treed75c27324c2799748fb32ff7639c78182148b054
parent9aa9fab90ce3f906a8a5591b744a385ed10a510e (diff)
downloadillumos-joyent-c42872d4489d6f0fbccfabe2a62f3c976ee1e5d6.tar.gz
6260724 PSARC/2005/067 CPU Power Management independent of autopm
6483153 pmconfig/dtpower/sysidpm should be lint-clean
-rw-r--r--usr/src/Makefile.lint1
-rw-r--r--usr/src/cmd/power/handlers.c71
-rw-r--r--usr/src/cmd/power/parse.c9
-rw-r--r--usr/src/cmd/power/pmconfig.h9
-rw-r--r--usr/src/cmd/power/power_all.xcl9
-rw-r--r--usr/src/cmd/power/powerd.c41
-rw-r--r--usr/src/cmd/power/sysstat.c10
-rw-r--r--usr/src/uts/common/io/pm.c186
-rw-r--r--usr/src/uts/common/os/sunpm.c103
-rw-r--r--usr/src/uts/common/sys/epm.h41
-rw-r--r--usr/src/uts/common/sys/pm.h20
-rw-r--r--usr/src/uts/sun4u/io/us_drv.c14
12 files changed, 383 insertions, 131 deletions
diff --git a/usr/src/Makefile.lint b/usr/src/Makefile.lint
index 1743cfebc3..e11d7f0c1c 100644
--- a/usr/src/Makefile.lint
+++ b/usr/src/Makefile.lint
@@ -207,6 +207,7 @@ COMMON_SUBDIRS = \
cmd/picl/prtpicl \
cmd/plockstat \
cmd/pools \
+ cmd/power \
cmd/ppgsz \
cmd/praudit \
cmd/prctl \
diff --git a/usr/src/cmd/power/handlers.c b/usr/src/cmd/power/handlers.c
index 1c3b2ff00e..44df1f5c30 100644
--- a/usr/src/cmd/power/handlers.c
+++ b/usr/src/cmd/power/handlers.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -56,6 +55,42 @@ static char always_on[] = "always-on";
/*
+ * Check for valid cpupm behavior and communicate it to the kernel.
+ */
+int
+cpupm(void)
+{
+ struct btoc {
+ char *behavior;
+ int cmd;
+ int Errno;
+ };
+ static struct btoc blist[] = {
+ "disable", PM_STOP_CPUPM, EINVAL,
+ "enable", PM_START_CPUPM, EBUSY,
+ NULL, 0, 0
+ };
+ struct btoc *bp;
+ char *behavior;
+
+ for (behavior = LINEARG(1), bp = blist; bp->cmd; bp++) {
+ if (strcmp(behavior, bp->behavior) == 0)
+ break;
+ }
+ if (bp->cmd == 0) {
+ mesg(MERR, "invalid cpupm behavior \"%s\"\n", behavior);
+ return (NOUP);
+ }
+ if (ioctl(pm_fd, bp->cmd, NULL) == -1 && errno != bp->Errno) {
+ mesg(MERR, "cpupm %s failed, %s\n",
+ behavior, strerror(errno));
+ return (NOUP);
+ }
+ return (OKUP);
+}
+
+
+/*
* Check for valid autopm behavior and save after ioctl success.
*/
int
@@ -673,10 +708,10 @@ sfpath(void)
/*
- * Try setting system threshold.
+ * Common function to set a system or cpu threshold.
*/
-int
-systhr(void)
+static int
+cmnthr(int req)
{
int value, nerr = 0, upval = OKUP;
char *thresh = LINEARG(1);
@@ -688,11 +723,31 @@ systhr(void)
upval = NOUP;
}
if (upval == OKUP)
- (void) ioctl(pm_fd, PM_SET_SYSTEM_THRESHOLD, value);
+ (void) ioctl(pm_fd, req, value);
return (upval);
}
+/*
+ * Try setting system threshold.
+ */
+int
+systhr(void)
+{
+ return (cmnthr(PM_SET_SYSTEM_THRESHOLD));
+}
+
+
+/*
+ * Try setting cpu threshold.
+ */
+int
+cputhr(void)
+{
+ return (cmnthr(PM_SET_CPU_THRESHOLD));
+}
+
+
int
tchars(void)
{
diff --git a/usr/src/cmd/power/parse.c b/usr/src/cmd/power/parse.c
index 0d291f9257..650e2154cb 100644
--- a/usr/src/cmd/power/parse.c
+++ b/usr/src/cmd/power/parse.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -56,6 +55,8 @@ prmup_t pm_status = { 0, OKUP, "pm" };
static cinfo_t conftab[] = {
"autopm", autopm, &pm_status, NULL, 2, 0, 1,
"autoshutdown", autosd, &cpr_status, as_cmt, 5, 0, 1,
+ "cpu-threshold", cputhr, &pm_status, NULL, 2, 0, 1,
+ "cpupm", cpupm, &pm_status, NULL, 2, 0, 1,
"device-dependency-property",
ddprop, &pm_status, NULL, 3, 1, 1,
"device-dependency", devdep, &pm_status, NULL, 3, 1, 1,
diff --git a/usr/src/cmd/power/pmconfig.h b/usr/src/cmd/power/pmconfig.h
index db59d2adf5..e48c9a0289 100644
--- a/usr/src/cmd/power/pmconfig.h
+++ b/usr/src/cmd/power/pmconfig.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -121,6 +120,8 @@ extern void parse_conf_file(char *, vact_t);
*/
extern int autopm(void);
extern int autosd(void);
+extern int cpupm(void);
+extern int cputhr(void);
extern int ddprop(void);
extern int devdep(void);
extern int devthr(void);
diff --git a/usr/src/cmd/power/power_all.xcl b/usr/src/cmd/power/power_all.xcl
index d8c0221c71..61baf7b7a4 100644
--- a/usr/src/cmd/power/power_all.xcl
+++ b/usr/src/cmd/power/power_all.xcl
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -112,3 +111,5 @@ msgid "pm ioctl, cmd %d, errno %d\n"
msgid "got scaled value %d\n"
msgid "threshold list"
msgid "idle path"
+msgid "cpu-threshold"
+msgid "cpupm"
diff --git a/usr/src/cmd/power/powerd.c b/usr/src/cmd/power/powerd.c
index de58520025..19e137ce02 100644
--- a/usr/src/cmd/power/powerd.c
+++ b/usr/src/cmd/power/powerd.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -109,7 +108,9 @@ 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;
@@ -139,7 +140,7 @@ static void check_idleness(time_t *, hrtime_t *);
static int last_system_activity(hrtime_t *);
static int run_idlecheck(void);
static void set_alarm(time_t);
-static int poweroff(char *, char **);
+static int poweroff(const char *, char **);
static int is_ok2shutdown(time_t *);
static int get_prom(int, prom_node_t, char *, char *, size_t);
static void power_button_monitor(void *);
@@ -153,9 +154,9 @@ static void *attach_devices(void *);
#endif
-/* VARARGS0 */
+/* PRINTFLIKE1 */
static void
-logerror(char *fmt, ...)
+logerror(const char *fmt, ...)
{
va_list args;
@@ -217,7 +218,7 @@ main(int argc, char *argv[])
pm_fd = open(PM, O_RDWR);
if (pm_fd == -1) {
- (void) sprintf(errmsg, "%s: %s", prog, PM);
+ (void) snprintf(errmsg, sizeof (errmsg), "%s: %s", prog, PM);
perror(errmsg);
exit(EXIT_FAILURE);
}
@@ -234,7 +235,7 @@ main(int argc, char *argv[])
}
if ((info = (pwr_info_t *)malloc(sizeof (pwr_info_t))) == NULL) {
- (void) sprintf(errmsg, "%s: malloc", prog);
+ (void) snprintf(errmsg, sizeof (errmsg), "%s: malloc", prog);
perror(errmsg);
exit(EXIT_FAILURE);
}
@@ -720,7 +721,7 @@ is_ok2shutdown(time_t *now)
/*
* Allow 10% of power_cycle_limit as free cycles.
*/
- free_cycles = power_cycle_limit * 0.1;
+ free_cycles = power_cycle_limit / 10;
power_cycles = atoi(power_cycles_st);
if (power_cycles < 0)
@@ -758,8 +759,8 @@ is_ok2shutdown(time_t *now)
* need to spread (power_cycle_limit - free_cycles) over the entire
* 7-year life span instead of (lifetime - date free_cycles ended).
*/
- scaled_cycles = ((float)life_passed / (float)LIFETIME_SECS) *
- (power_cycle_limit - free_cycles);
+ scaled_cycles = (int)(((float)life_passed / (float)LIFETIME_SECS) *
+ (power_cycle_limit - free_cycles));
if (no_power_cycles)
goto ckdone;
@@ -912,7 +913,7 @@ set_alarm(time_t now)
}
static int
-poweroff(char *msg, char **cmd_argv)
+poweroff(const char *msg, char **cmd_argv)
{
struct stat statbuf;
pid_t pid, child;
@@ -1193,14 +1194,14 @@ static int
open_pidfile(char *me)
{
int fd;
- char *e1 = "%s: Cannot open pid file for read: ";
- char *e2 = "%s: Cannot unlink obsolete pid file: ";
- char *e3 = "%s: Cannot open /proc for pid %ld: ";
- char *e4 = "%s: Cannot read /proc for pid %ld: ";
- char *e5 = "%s: Another instance (pid %ld) is trying to exit"
+ const char *e1 = "%s: Cannot open pid file for read: ";
+ const char *e2 = "%s: Cannot unlink obsolete pid file: ";
+ 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";
- char *e6 = "%s: Another daemon is running\n";
- char *e7 = "%s: Cannot create pid file: ";
+ const char *e6 = "%s: Another daemon is running\n";
+ const char *e7 = "%s: Cannot create pid file: ";
again:
if ((fd = open(pidpath, O_CREAT | O_EXCL | O_WRONLY, 0444)) == -1) {
diff --git a/usr/src/cmd/power/sysstat.c b/usr/src/cmd/power/sysstat.c
index c1b0806665..a6bc12d1b0 100644
--- a/usr/src/cmd/power/sysstat.c
+++ b/usr/src/cmd/power/sysstat.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 1995-2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
@@ -589,6 +588,7 @@ static void
fail(char *fmt, ...)
{
char new_fmt[256];
+ const char *fmtptr = new_fmt;
va_list args;
size_t len;
@@ -597,7 +597,7 @@ fail(char *fmt, ...)
if (snprintf(new_fmt, len, "powerd: %s", fmt) > len)
syslog(LOG_ERR, "powerd: syslog message too large");
else
- vsyslog(LOG_ERR, new_fmt, args);
+ vsyslog(LOG_ERR, fmtptr, args);
va_end(args);
thr_exit((void *) 0);
diff --git a/usr/src/uts/common/io/pm.c b/usr/src/uts/common/io/pm.c
index b98022ca8b..c46ad7ea0a 100644
--- a/usr/src/uts/common/io/pm.c
+++ b/usr/src/uts/common/io/pm.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -72,6 +71,10 @@
extern kmutex_t pm_scan_lock; /* protects autopm_enable, pm_scans_disabled */
extern kmutex_t pm_clone_lock; /* protects pm_clones array */
extern int autopm_enabled;
+extern pm_cpupm_t cpupm;
+extern int pm_default_idle_threshold;
+extern int pm_system_idle_threshold;
+extern int pm_cpu_idle_threshold;
extern kcondvar_t pm_clones_cv[PM_MAX_CLONE];
extern uint_t pm_poll_cnt[PM_MAX_CLONE];
@@ -422,6 +425,12 @@ static struct pm_cmd_info pmci[] = {
{PM_GET_TIME_IDLE, "PM_GET_TIME_IDLE", 1, PM_REQ, INWHO, DIP, NODEP},
{PM_ADD_DEPENDENT_PROPERTY, "PM_ADD_DEPENDENT_PROPERTY", 1, PM_REQ,
INWHO | INDATASTRING, NODIP, DEP, SU},
+ {PM_START_CPUPM, "PM_START_CPUPM", 1, NOSTRUCT, 0, 0, 0, SU},
+ {PM_STOP_CPUPM, "PM_STOP_CPUPM", 1, NOSTRUCT, 0, 0, 0, SU},
+ {PM_GET_CPU_THRESHOLD, "PM_GET_CPU_THRESHOLD", 1, NOSTRUCT},
+ {PM_SET_CPU_THRESHOLD, "PM_SET_CPU_THRESHOLD", 1, NOSTRUCT,
+ 0, 0, 0, SU},
+ {PM_GET_CPUPM_STATE, "PM_GET_CPUPM_STATE", 1, NOSTRUCT},
{0, NULL}
};
@@ -455,22 +464,36 @@ pm_decode_cmd(int cmd)
int
pm_start_pm_walk(dev_info_t *dip, void *arg)
{
- char *cmdstr = pm_decode_cmd(*((int *)arg));
+ int cmd = *((int *)arg);
+ char *cmdstr = pm_decode_cmd(cmd);
if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip))
return (DDI_WALK_CONTINUE);
- /*
- * Construct per dip scan taskq
- */
- mutex_enter(&pm_scan_lock);
- if (autopm_enabled)
- pm_scan_init(dip);
- mutex_exit(&pm_scan_lock);
+ switch (cmd) {
+ case PM_START_CPUPM:
+ if (!PM_ISCPU(dip))
+ return (DDI_WALK_CONTINUE);
+ mutex_enter(&pm_scan_lock);
+ if (!PM_CPUPM_DISABLED)
+ pm_scan_init(dip);
+ mutex_exit(&pm_scan_lock);
+ break;
+ case PM_START_PM:
+ mutex_enter(&pm_scan_lock);
+ if (PM_ISCPU(dip) && PM_CPUPM_DISABLED) {
+ mutex_exit(&pm_scan_lock);
+ return (DDI_WALK_CONTINUE);
+ }
+ if (autopm_enabled)
+ pm_scan_init(dip);
+ mutex_exit(&pm_scan_lock);
+ break;
+ }
/*
* Start doing pm on device: ensure pm_scan data structure initiated,
- * no need to gurantee a successful scan run.
+ * no need to guarantee a successful scan run.
*/
PMD(PMD_SCAN | PMD_IOCTL, ("ioctl: %s: scan %s@%s(%s#%d)\n", cmdstr,
PM_DEVICE(dip)))
@@ -486,10 +509,32 @@ int
pm_stop_pm_walk(dev_info_t *dip, void *arg)
{
pm_info_t *info = PM_GET_PM_INFO(dip);
- char *cmdstr = pm_decode_cmd(*((int *)arg));
+ int cmd = *((int *)arg);
+ char *cmdstr = pm_decode_cmd(cmd);
if (!info)
return (DDI_WALK_CONTINUE);
+
+ switch (cmd) {
+ case PM_STOP_PM:
+ /*
+ * If CPU devices are being managed independently, then don't
+ * stop them as part of PM_STOP_PM. Only stop them as part of
+ * PM_STOP_CPUPM and PM_RESET_PM.
+ */
+ if (PM_ISCPU(dip) && PM_CPUPM_ENABLED)
+ return (DDI_WALK_CONTINUE);
+ break;
+ case PM_STOP_CPUPM:
+ /*
+ * If stopping CPU devices and this device is not marked
+ * as a CPU device, then skip.
+ */
+ if (!PM_ISCPU(dip))
+ return (DDI_WALK_CONTINUE);
+ break;
+ }
+
/*
* Stop the current scan, and then bring it back to normal power.
*/
@@ -693,33 +738,49 @@ pm_discard_entries(int clone)
mutex_exit(&pm_clone_lock);
}
-int
-pm_set_sys_threshold(dev_info_t *dip, void *arg)
-{
- int pm_system_idle_threshold = *((int *)arg);
- pm_info_t *info = PM_GET_PM_INFO(dip);
- int processed = 0;
-
- if (!info)
- return (DDI_WALK_CONTINUE);
+static void
+pm_set_idle_threshold(dev_info_t *dip, int thresh, int flag)
+{
if (!PM_ISBC(dip) && !PM_ISDIRECT(dip)) {
switch (DEVI(dip)->devi_pm_flags & PMC_THRESH_ALL) {
case PMC_DEF_THRESH:
- PMD(PMD_IOCTL, ("ioctl: set_sys_threshold: set "
+ case PMC_CPU_THRESH:
+ PMD(PMD_IOCTL, ("ioctl: set_idle_threshold: set "
"%s@%s(%s#%d) default thresh to 0t%d\n",
- PM_DEVICE(dip), pm_system_idle_threshold))
- pm_set_device_threshold(dip, pm_system_idle_threshold,
- PMC_DEF_THRESH);
- processed++;
+ PM_DEVICE(dip), thresh))
+ pm_set_device_threshold(dip, thresh, flag);
break;
default:
break;
}
}
+}
+
+static int
+pm_set_idle_thresh_walk(dev_info_t *dip, void *arg)
+{
+ int cmd = *((int *)arg);
+
+ if (!PM_GET_PM_INFO(dip))
+ return (DDI_WALK_CONTINUE);
- if (processed && autopm_enabled)
+ switch (cmd) {
+ case PM_SET_SYSTEM_THRESHOLD:
+ if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
+ break;
+ pm_set_idle_threshold(dip, pm_system_idle_threshold,
+ PMC_DEF_THRESH);
+ pm_rescan(dip);
+ break;
+ case PM_SET_CPU_THRESHOLD:
+ if (!PM_ISCPU(dip))
+ break;
+ pm_set_idle_threshold(dip, pm_cpu_idle_threshold,
+ PMC_CPU_THRESH);
pm_rescan(dip);
+ break;
+ }
return (DDI_WALK_CONTINUE);
}
@@ -846,8 +907,6 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
pm_state_change_t *pscp;
pm_state_change_t psc;
size_t copysize;
- extern int pm_default_idle_threshold;
- extern int pm_system_idle_threshold;
extern void pm_record_thresh(pm_thresh_rec_t *);
psce_t *pm_psc_clone_to_direct(int);
psce_t *pm_psc_clone_to_interest(int);
@@ -1555,8 +1614,12 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
break;
}
pm_unrecord_threshold(req.physpath);
- pm_set_device_threshold(dip, pm_system_idle_threshold,
- PMC_DEF_THRESH);
+ if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
+ pm_set_device_threshold(dip,
+ pm_cpu_idle_threshold, PMC_CPU_THRESH);
+ else
+ pm_set_device_threshold(dip,
+ pm_system_idle_threshold, PMC_DEF_THRESH);
ret = 0;
break;
}
@@ -2089,6 +2152,9 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
case PMC_COMP_THRESH:
*rval_p = PM_COMPONENT_THRESHOLD;
break;
+ case PMC_CPU_THRESH:
+ *rval_p = PM_CPU_THRESHOLD;
+ break;
default:
if (PM_ISBC(dip)) {
*rval_p = PM_OLD_THRESHOLD;
@@ -2419,15 +2485,20 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
case NOSTRUCT:
switch (cmd) {
case PM_START_PM:
+ case PM_START_CPUPM:
mutex_enter(&pm_scan_lock);
- if (autopm_enabled) {
+ if ((cmd == PM_START_PM && autopm_enabled) ||
+ (cmd == PM_START_CPUPM && PM_CPUPM_ENABLED)) {
mutex_exit(&pm_scan_lock);
PMD(PMD_ERROR, ("ioctl: %s: EBUSY\n",
cmdstr))
ret = EBUSY;
break;
}
- autopm_enabled = 1;
+ if (cmd == PM_START_PM)
+ autopm_enabled = 1;
+ else
+ cpupm = PM_CPUPM_ENABLE;
mutex_exit(&pm_scan_lock);
ddi_walk_devs(ddi_root_node(), pm_start_pm_walk, &cmd);
ret = 0;
@@ -2435,30 +2506,41 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
case PM_RESET_PM:
case PM_STOP_PM:
+ case PM_STOP_CPUPM:
{
extern void pm_discard_thresholds(void);
mutex_enter(&pm_scan_lock);
- if (!autopm_enabled && cmd != PM_RESET_PM) {
+ if ((cmd == PM_STOP_PM && !autopm_enabled) ||
+ (cmd == PM_STOP_CPUPM && PM_CPUPM_DISABLED)) {
mutex_exit(&pm_scan_lock);
PMD(PMD_ERROR, ("ioctl: %s: EINVAL\n",
cmdstr))
ret = EINVAL;
break;
}
- autopm_enabled = 0;
+ if (cmd == PM_STOP_PM)
+ autopm_enabled = 0;
+ else if (cmd == PM_STOP_CPUPM)
+ cpupm = PM_CPUPM_DISABLE;
+ else {
+ autopm_enabled = 0;
+ cpupm = PM_CPUPM_NOTSET;
+ }
mutex_exit(&pm_scan_lock);
+
/*
* bring devices to full power level, stop scan
*/
ddi_walk_devs(ddi_root_node(), pm_stop_pm_walk, &cmd);
ret = 0;
- if (cmd == PM_STOP_PM)
+ if (cmd == PM_STOP_PM || cmd == PM_STOP_CPUPM)
break;
/*
* Now do only PM_RESET_PM stuff.
*/
pm_system_idle_threshold = pm_default_idle_threshold;
+ pm_cpu_idle_threshold = 0;
pm_discard_thresholds();
pm_all_to_default_thresholds();
pm_dispatch_to_dep_thread(PM_DEP_WK_REMOVE_DEP,
@@ -2476,7 +2558,13 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
ret = 0;
break;
+ case PM_GET_CPU_THRESHOLD:
+ *rval_p = pm_cpu_idle_threshold;
+ ret = 0;
+ break;
+
case PM_SET_SYSTEM_THRESHOLD:
+ case PM_SET_CPU_THRESHOLD:
if ((int)arg < 0) {
PMD(PMD_ERROR, ("ioctl: %s: arg 0x%x < 0"
"--EINVAL\n", cmdstr, (int)arg))
@@ -2485,9 +2573,14 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
}
PMD(PMD_IOCTL, ("ioctl: %s: 0x%x 0t%d\n", cmdstr,
(int)arg, (int)arg))
- pm_system_idle_threshold = (int)arg;
- ddi_walk_devs(ddi_root_node(), pm_set_sys_threshold,
- (void *) &pm_system_idle_threshold);
+ if (cmd == PM_SET_SYSTEM_THRESHOLD)
+ pm_system_idle_threshold = (int)arg;
+ else {
+ pm_cpu_idle_threshold = (int)arg;
+ }
+ ddi_walk_devs(ddi_root_node(), pm_set_idle_thresh_walk,
+ (void *) &cmd);
+
ret = 0;
break;
@@ -2507,10 +2600,19 @@ pm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
}
ret = 0;
break;
+
+ case PM_GET_CPUPM_STATE:
+ if (PM_CPUPM_ENABLED)
+ *rval_p = PM_CPU_PM_ENABLED;
+ else if (PM_CPUPM_DISABLED)
+ *rval_p = PM_CPU_PM_DISABLED;
+ else
+ *rval_p = PM_CPU_PM_NOTSET;
+ ret = 0;
+ break;
}
break;
-
default:
/*
* Internal error, invalid ioctl description
diff --git a/usr/src/uts/common/os/sunpm.c b/usr/src/uts/common/os/sunpm.c
index 997ca125dd..193a8598c1 100644
--- a/usr/src/uts/common/os/sunpm.c
+++ b/usr/src/uts/common/os/sunpm.c
@@ -61,10 +61,14 @@
* readable strings (currently unused) for each component name and power state.
* Devices which export pm-components(9P) are automatically power managed
* whenever autopm is enabled (via PM_START_PM ioctl issued by pmconfig(1M)
- * after parsing power.conf(4)).
- * For these devices, all components are considered independent of each other,
- * and it is up to the driver to decide when a transition requires saving or
- * restoring hardware state.
+ * after parsing power.conf(4)). The exception to this rule is that power
+ * manageable CPU devices may be automatically managed independently of autopm
+ * by either enabling or disabling (via PM_START_CPUPM and PM_STOP_CPUPM
+ * ioctls) cpupm. If the CPU devices are not managed independently, then they
+ * are managed by autopm. In either case, for automatically power managed
+ * devices, all components are considered independent of each other, and it is
+ * up to the driver to decide when a transition requires saving or restoring
+ * hardware state.
*
* Each device component also has a threshold time associated with each power
* transition (see power.conf(4)), and a busy/idle state maintained by the
@@ -78,8 +82,9 @@
* -set threshold values (defaults if none provided by pmconfig)
* -set dependencies among devices
* -enable/disable autopm
- * -turn down idle components based on thresholds (if autopm is enabled)
- * (aka scanning)
+ * -enable/disable cpupm
+ * -turn down idle components based on thresholds (if autopm or cpupm is
+ * enabled) (aka scanning)
* -maintain power states based on dependencies among devices
* -upon request, or when the frame buffer powers off, attempt to turn off
* all components that are idle or become idle over the next (10 sec)
@@ -99,9 +104,10 @@
* property
*
* Scanning:
- * Whenever autopm is enabled, the framework attempts to bring each component
- * of each device to its lowest power based on the threshold of idleness
- * associated with each transition and the busy/idle state of the component.
+ * Whenever autopm or cpupm is enabled, the framework attempts to bring each
+ * component of each managed device to its lowest power based on the threshold
+ * of idleness associated with each transition and the busy/idle state of the
+ * component.
*
* The actual work of this is done by pm_scan_dev(), which cycles through each
* component of a device, checking its idleness against its current threshold,
@@ -177,8 +183,8 @@
*
* pm_scan_lock:
* It protects the timeout id of the scan thread, and the value
- * of autopm_enabled. This lock is not held concurrently with
- * any other PM locks.
+ * of autopm_enabled and cpupm. This lock is not held
+ * concurrently with any other PM locks.
*
* pm_clone_lock: Protects the clone list and count of poll events
* pending for the pm driver.
@@ -326,6 +332,13 @@ pm_dep_wk_t *pm_dep_thread_tail = NULL;
int autopm_enabled;
/*
+ * cpupm is turned on and off, by the PM_START_CPUPM and PM_STOP_CPUPM ioctls,
+ * to define the power management behavior of CPU devices separate from
+ * autopm. Protected by pm_scan_lock.
+ */
+pm_cpupm_t cpupm = PM_CPUPM_NOTSET;
+
+/*
* This flag is true while processes are stopped for a checkpoint/resume.
* Controlling processes of direct pm'd devices are not available to
* participate in power level changes, so we bypass them when this is set.
@@ -379,6 +392,8 @@ kmutex_t pm_remdrv_lock;
int pm_default_idle_threshold = PM_DEFAULT_SYS_IDLENESS;
int pm_system_idle_threshold;
+int pm_cpu_idle_threshold;
+
/*
* By default nexus has 0 threshold, and depends on its children to keep it up
*/
@@ -521,6 +536,7 @@ pm_cpr_callb(void *arg, int code)
{
_NOTE(ARGUNUSED(arg))
static int auto_save;
+ static pm_cpupm_t cpupm_save;
static int pm_reset_timestamps(dev_info_t *, void *);
switch (code) {
@@ -535,12 +551,15 @@ pm_cpr_callb(void *arg, int code)
pm_scans_disabled = 1;
auto_save = autopm_enabled;
autopm_enabled = 0;
+ cpupm_save = cpupm;
+ cpupm = PM_CPUPM_NOTSET;
mutex_exit(&pm_scan_lock);
ddi_walk_devs(ddi_root_node(), pm_scan_stop_walk, NULL);
break;
case CB_CODE_CPR_RESUME:
ASSERT(!autopm_enabled);
+ ASSERT(cpupm == PM_CPUPM_NOTSET);
ASSERT(pm_scans_disabled);
pm_scans_disabled = 0;
/*
@@ -553,6 +572,7 @@ pm_cpr_callb(void *arg, int code)
ddi_walk_devs(ddi_root_node(), pm_reset_timestamps, NULL);
autopm_enabled = auto_save;
+ cpupm = cpupm_save;
/*
* If there is any auto-pm device, get the scanning
* going. Otherwise don't bother.
@@ -598,6 +618,7 @@ pm_init(void)
pm_comps_notlowest = 0;
pm_system_idle_threshold = pm_default_idle_threshold;
+ pm_cpu_idle_threshold = 0;
pm_cpr_cb_id = callb_add(pm_cpr_callb, (void *)NULL,
CB_CL_CPR_PM, "pm_cpr");
@@ -628,10 +649,10 @@ pm_init(void)
}
/*
- * pm_scan_init - create pm scan data structure. Called (if autopm enabled)
- * when device becomes power managed or after a failed detach and when autopm
- * is started via PM_START_PM ioctl, and after a CPR resume to get all the
- * devices scanning again.
+ * pm_scan_init - create pm scan data structure. Called (if autopm or cpupm
+ * enabled) when device becomes power managed or after a failed detach and
+ * when autopm is started via PM_START_PM or PM_START_CPUPM ioctls, and after
+ * a CPR resume to get all the devices scanning again.
*/
void
pm_scan_init(dev_info_t *dip)
@@ -873,7 +894,7 @@ pm_rescan(void *arg)
PM_LOCK_DIP(dip);
info = PM_GET_PM_INFO(dip);
scanp = PM_GET_PM_SCAN(dip);
- if (pm_scans_disabled || !autopm_enabled || !info || !scanp ||
+ if (pm_scans_disabled || !PM_SCANABLE(dip) || !info || !scanp ||
(scanp->ps_scan_flags & PM_SCAN_STOP)) {
PM_UNLOCK_DIP(dip);
return;
@@ -955,7 +976,7 @@ pm_scan(void *arg)
scanp = PM_GET_PM_SCAN(dip);
ASSERT(scanp && PM_GET_PM_INFO(dip));
- if (pm_scans_disabled || !autopm_enabled ||
+ if (pm_scans_disabled || !PM_SCANABLE(dip) ||
(scanp->ps_scan_flags & PM_SCAN_STOP)) {
scanp->ps_scan_flags &= ~(PM_SCAN_AGAIN | PM_SCAN_DISPATCHED);
PM_UNLOCK_DIP(dip);
@@ -1130,15 +1151,16 @@ pm_scan_dev(dev_info_t *dip)
PM_KUC(dip)))
/* no scan under the following conditions */
- if (pm_scans_disabled || !autopm_enabled ||
+ if (pm_scans_disabled || !PM_SCANABLE(dip) ||
(scanp->ps_scan_flags & PM_SCAN_STOP) ||
(PM_KUC(dip) != 0) ||
PM_ISDIRECT(dip) || pm_noinvol(dip)) {
PM_UNLOCK_DIP(dip);
PMD(PMD_SCAN, ("%s: [END, %s@%s(%s#%d)] no scan, "
- "scan_disabled(%d), apm_enabled(%d), kuc(%d), "
- "%s directpm, %s pm_noinvol\n", pmf, PM_DEVICE(dip),
- pm_scans_disabled, autopm_enabled, PM_KUC(dip),
+ "scan_disabled(%d), apm_enabled(%d), cpupm(%d), "
+ "kuc(%d), %s directpm, %s pm_noinvol\n",
+ pmf, PM_DEVICE(dip), pm_scans_disabled, autopm_enabled,
+ cpupm, PM_KUC(dip),
PM_ISDIRECT(dip) ? "is" : "is not",
pm_noinvol(dip) ? "is" : "is not"))
return (LONG_MAX);
@@ -2461,9 +2483,12 @@ pm_lower_power(dev_info_t *dip, int comp, int level)
* If we don't care about saving power, or we're treating this node
* specially, then this is a no-op
*/
- if (!autopm_enabled || pm_noinvol(dip)) {
- PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) %s%s\n", pmf, PM_DEVICE(dip),
+ if (!PM_SCANABLE(dip) || pm_noinvol(dip)) {
+ PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) %s%s%s%s\n",
+ pmf, PM_DEVICE(dip),
!autopm_enabled ? "!autopm_enabled " : "",
+ !PM_CPUPM_ENABLED ? "!cpupm_enabled " : "",
+ PM_CPUPM_DISABLED ? "cpupm_disabled " : "",
pm_noinvol(dip) ? "pm_noinvol()" : ""))
return (DDI_SUCCESS);
}
@@ -3258,7 +3283,7 @@ pm_detach_failed(dev_info_t *dip)
}
if (!PM_ISBC(dip)) {
mutex_enter(&pm_scan_lock);
- if (autopm_enabled)
+ if (PM_SCANABLE(dip))
pm_scan_init(dip);
mutex_exit(&pm_scan_lock);
pm_rescan(dip);
@@ -3387,8 +3412,12 @@ pm_premanage(dev_info_t *dip, int style)
ASSERT(PM_CP(dip, i)->pmc_cur_pwr == 0);
e_pm_set_cur_pwr(dip, PM_CP(dip, i), PM_LEVEL_UNKNOWN);
}
- pm_set_device_threshold(dip, pm_system_idle_threshold,
- PMC_DEF_THRESH);
+ if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
+ pm_set_device_threshold(dip, pm_cpu_idle_threshold,
+ PMC_CPU_THRESH);
+ else
+ pm_set_device_threshold(dip, pm_system_idle_threshold,
+ PMC_DEF_THRESH);
kmem_free(compp, cmpts * sizeof (pm_comp_t));
}
return (DDI_SUCCESS);
@@ -3448,7 +3477,7 @@ e_pm_manage(dev_info_t *dip, int style)
if (!PM_ISBC(dip)) {
mutex_enter(&pm_scan_lock);
- if (autopm_enabled) {
+ if (PM_SCANABLE(dip)) {
pm_scan_init(dip);
mutex_exit(&pm_scan_lock);
pm_rescan(dip);
@@ -3508,6 +3537,8 @@ cur_threshold(dev_info_t *dip, int comp)
int thresh;
if (DEVI(dip)->devi_pm_flags & PMC_NEXDEF_THRESH)
thresh = pm_default_nexus_threshold;
+ else if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
+ thresh = pm_cpu_idle_threshold;
else
thresh = pm_system_idle_threshold;
return (thresh);
@@ -4634,6 +4665,20 @@ e_pm_props(dev_info_t *dip)
if (ddi_prop_exists(DDI_DEV_T_ANY, dip, propflag,
"no-involuntary-power-cycles"))
flags |= PMC_NO_INVOL;
+ /*
+ * Is the device a CPU device?
+ */
+ if (ddi_getlongprop(DDI_DEV_T_ANY, dip, propflag, "pm-class",
+ (caddr_t)&pp, &len) == DDI_PROP_SUCCESS) {
+ if (strcmp(pp, "CPU") == 0) {
+ flags |= PMC_CPU_DEVICE;
+ } else {
+ cmn_err(CE_NOTE, "!device %s@%s has unrecognized "
+ "%s property value '%s'", PM_NAME(dip),
+ PM_ADDR(dip), "pm-class", pp);
+ }
+ kmem_free(pp, len);
+ }
/* devfs single threads us */
DEVI(dip)->devi_pm_flags |= flags;
}
@@ -5912,7 +5957,7 @@ pm_apply_recorded_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
pmf, PM_DEVICE(dip), ep->pte_thresh[0]))
PM_UNLOCK_DIP(dip);
pm_set_device_threshold(dip, ep->pte_thresh[0], PMC_DEV_THRESH);
- if (autopm_enabled)
+ if (PM_SCANABLE(dip))
pm_rescan(dip);
return;
}
@@ -5930,7 +5975,7 @@ pm_apply_recorded_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
DEVI(dip)->devi_pm_flags |= PMC_COMP_THRESH;
PM_UNLOCK_DIP(dip);
- if (autopm_enabled)
+ if (PM_SCANABLE(dip))
pm_rescan(dip);
}
diff --git a/usr/src/uts/common/sys/epm.h b/usr/src/uts/common/sys/epm.h
index 2088d3be4d..7d80cf2ac5 100644
--- a/usr/src/uts/common/sys/epm.h
+++ b/usr/src/uts/common/sys/epm.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -81,9 +80,11 @@ int e_new_pm_props(dev_info_t *);
#define PMC_CONSOLE_FB 0x10000 /* console framebuffer */
#define PMC_NOINVOL_DONE 0x20000 /* processed by pm_noinvol_specd() */
#define PMC_DRIVER_REMOVED 0x40000 /* driver is removed */
+#define PMC_CPU_DEVICE 0x80000 /* device is a power manageable CPU */
+#define PMC_CPU_THRESH 0x100000 /* cpu threshold set */
#define PMC_THRESH_ALL (PMC_DEF_THRESH | PMC_DEV_THRESH | \
- PMC_COMP_THRESH | PMC_NEXDEF_THRESH)
+ PMC_COMP_THRESH | PMC_NEXDEF_THRESH | PMC_CPU_THRESH)
#define PMC_THRESH_NONE ~(PMC_THRESH_ALL)
/* Flags for the component */
@@ -217,6 +218,13 @@ typedef enum pm_canblock
PM_CANBLOCK_BYPASS /* don't wait, ignore controlling process */
} pm_canblock_t;
+typedef enum pm_cpupm
+{
+ PM_CPUPM_NOTSET, /* no specific treatment of CPU devices */
+ PM_CPUPM_ENABLE, /* power manage CPU devices */
+ PM_CPUPM_DISABLE /* do not power manage CPU devices */
+} pm_cpupm_t;
+
/*
* The power request struct uses for the DDI_CTLOPS_POWER busctl.
*
@@ -546,6 +554,29 @@ typedef struct pm_thresh_rec {
*/
#define PM_SKBU(dip) (DEVI(dip)->devi_pm_flags & PMC_SKIP_BRINGUP)
+/*
+ * Returns true if device specified by dip is a power manageable CPU.
+ */
+#define PM_ISCPU(dip) (DEVI(dip)->devi_pm_flags & PMC_CPU_DEVICE)
+
+/*
+ * Returns true if cpupm is enabled.
+ */
+#define PM_CPUPM_ENABLED (cpupm == PM_CPUPM_ENABLE)
+
+/*
+ * Returns true if is disabled.
+ */
+#define PM_CPUPM_DISABLED (cpupm == PM_CPUPM_DISABLE)
+
+/*
+ * If (autopm is enabled and
+ * (CPUs are not disabled, or it isn't a cpu)) OR
+ * (CPUs are enabled and it is one)
+ */
+#define PM_SCANABLE(dip) ((autopm_enabled && \
+(!PM_CPUPM_DISABLED || !PM_ISCPU(dip))) || (PM_CPUPM_ENABLED && PM_ISCPU(dip)))
+
#define PM_NOT_ALL_LOWEST 0x0 /* not all components are at lowest */
#define PM_ALL_LOWEST 0x1 /* all components are at lowest lvl */
diff --git a/usr/src/uts/common/sys/pm.h b/usr/src/uts/common/sys/pm.h
index 3169e165fb..a65075b3a5 100644
--- a/usr/src/uts/common/sys/pm.h
+++ b/usr/src/uts/common/sys/pm.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -91,7 +90,12 @@ typedef enum {
PM_ADD_DEPENDENT, /* replaces PM_ADD_DEP */
PM_GET_TIME_IDLE, /* replaces PM_IDLE_TIME */
PM_GET_DEFAULT_SYSTEM_THRESHOLD,
- PM_ADD_DEPENDENT_PROPERTY
+ PM_ADD_DEPENDENT_PROPERTY,
+ PM_START_CPUPM,
+ PM_STOP_CPUPM,
+ PM_GET_CPU_THRESHOLD,
+ PM_SET_CPU_THRESHOLD,
+ PM_GET_CPUPM_STATE
} pm_cmds;
/*
@@ -220,7 +224,11 @@ typedef enum {
PM_DEVICE_THRESHOLD,
PM_COMPONENT_THRESHOLD,
PM_OLD_THRESHOLD,
- PM_DIRECTLY_MANAGED
+ PM_DIRECTLY_MANAGED,
+ PM_CPU_THRESHOLD,
+ PM_CPU_PM_ENABLED,
+ PM_CPU_PM_DISABLED,
+ PM_CPU_PM_NOTSET
} pm_states;
diff --git a/usr/src/uts/sun4u/io/us_drv.c b/usr/src/uts/sun4u/io/us_drv.c
index 781a7e1e21..6a4c825a3a 100644
--- a/usr/src/uts/sun4u/io/us_drv.c
+++ b/usr/src/uts/sun4u/io/us_drv.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -269,6 +268,13 @@ us_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
return (DDI_FAILURE);
}
+ if (ddi_prop_update_string(DDI_DEV_T_NONE,
+ usdsp->dip, "pm-class", "CPU") != DDI_PROP_SUCCESS) {
+ us_pm_free(usdsp);
+ ddi_soft_state_free(us_state, instance);
+ return (DDI_FAILURE);
+ }
+
/*
* Taskq is used to dispatch routine to monitor CPU activities.
*/