Date: Wed, 30 Jan 2008 17:56:19 -0500 From: "Alexandre \"Sunny\" Kovalenko" <alex.kovalenko@verizon.net> To: acpi@freebsd.org Subject: [RFC] Patch to enable temperature ceiling in powerd Message-ID: <1201733779.902.18.camel@RabbitsDen>
index | next in thread | raw e-mail
[-- Attachment #1 --]
Some time ago I have put together patch for powerd, which allows user to
specify the temperature threshold at which powerd will lower CPU
frequency no matter what the load was at the time. I recently had to
adapt it to the 7.0-PRERELEASE for someone with the overheating laptop,
which got me to think that it might be useful for someone else yet.
Basic idea is fairly simple -- check temperature in TZ0 and, if it has
reached certain value, either override frequency with the lowest
available (in the case of 'max' setting) or change idle time to 100% and
let adaptive algorithm decrease frequency gradually.
I imagine it also could be poor man's substitute for the low noise
acoustic policy ;)
If there is an interest, I will go ahead and submit a PR, otherwise it
will live in the mail archives for someone to find. Any comments,
suggestions or criticisms are welcome.
Temperature threshold (in Celsius) could be set by means of '-T' command
line option (as in '-T 60').
--
Alexandre "Sunny" Kovalenko (Олександр Коваленко)
[-- Attachment #2 --]
--- powerd.c.orig 2007-06-14 16:17:15.000000000 -0400
+++ powerd.c 2008-01-14 20:14:56.000000000 -0500
@@ -53,6 +53,7 @@
#define DEFAULT_ACTIVE_PERCENT 65
#define DEFAULT_IDLE_PERCENT 90
#define DEFAULT_POLL_INTERVAL 500 /* Poll interval in milliseconds */
+#define VERY_HIGH_TEMPERATURE 200 /* Unlikely to be reached in the hardware lifetime */
typedef enum {
MODE_MIN,
@@ -93,11 +94,13 @@
static int freq_mib[4];
static int levels_mib[4];
static int acline_mib[3];
+static int temp_mib[5];
/* Configuration */
static int cpu_running_mark;
static int cpu_idle_mark;
static int poll_ival;
+static int passive_cooling_mark;
static int vflag;
static volatile sig_atomic_t exit_requested;
@@ -357,7 +360,7 @@
{
fprintf(stderr,
-"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile]\n");
+"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile] [-T temperature]\n");
exit(1);
}
@@ -371,6 +374,7 @@
const char *pidfile = NULL;
long idle, total;
int curfreq, *freqs, i, *mwatts, numfreqs;
+ int temperature;
int ch, mode, mode_ac, mode_battery, mode_none;
uint64_t mjoules_used;
size_t len;
@@ -381,13 +385,14 @@
cpu_idle_mark = DEFAULT_IDLE_PERCENT;
poll_ival = DEFAULT_POLL_INTERVAL;
mjoules_used = 0;
+ passive_cooling_mark = VERY_HIGH_TEMPERATURE;
vflag = 0;
/* User must be root to control frequencies. */
if (geteuid() != 0)
errx(1, "must be root to run");
- while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:v")) != EOF)
+ while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:T:v")) != EOF)
switch (ch) {
case 'a':
parse_mode(optarg, &mode_ac, ch);
@@ -424,6 +429,16 @@
usage();
}
break;
+ case 'T':
+ passive_cooling_mark = atoi(optarg);
+ if(passive_cooling_mark < 0 || passive_cooling_mark > VERY_HIGH_TEMPERATURE) {
+ warnx("%d is not valid temperature for passive cooling",
+ passive_cooling_mark);
+ usage();
+ }
+ passive_cooling_mark *= 10;
+ passive_cooling_mark += 2733;
+ break;
case 'v':
vflag = 1;
break;
@@ -446,6 +461,9 @@
len = 4;
if (sysctlnametomib("dev.cpu.0.freq_levels", levels_mib, &len))
err(1, "lookup freq_levels");
+ len = 5;
+ if (sysctlnametomib("hw.acpi.thermal.tz0.temperature", temp_mib, &len))
+ err(1, "lookup temperature");
/* Check if we can read the idle time and supported freqs. */
if (read_usage_times(NULL, NULL))
@@ -528,6 +546,10 @@
warn("error reading current CPU frequency");
continue;
}
+ /* Read current temperature. */
+ len = sizeof(temperature);
+ if(sysctl(temp_mib, 5, &temperature, &len, NULL, 0))
+ err(1, "error reading current temperature");
if (vflag) {
for (i = 0; i < numfreqs; i++) {
@@ -571,6 +593,17 @@
if (set_freq(freqs[0]) != 0) {
warn("error setting CPU freq %d",
freqs[0]);
+ /* Check for passive cooling override */
+ if(temperature > passive_cooling_mark) {
+ if (vflag) {
+ printf("passive cooling override; "
+ "changing frequency to %d MHz\n",
+ freqs[numfreqs - 1]);
+ }
+ if (set_freq(freqs[numfreqs - 1]))
+ err(1, "error setting CPU freq %d",
+ freqs[numfreqs - 1]);
+ }
continue;
}
}
@@ -583,6 +616,14 @@
warn("read_usage_times() failed");
continue;
}
+ /*
+ * If temperature has risen over passive cooling mark, we
+ * would want to decrease frequency regardless of the load,
+ * Simplest way to go about this would be to report 100%
+ * idle CPU and let adaptive algorithm do its job.
+ */
+ if(temperature > passive_cooling_mark)
+ idle = total;
/*
* If we're idle less than the active mark, bump up two levels.
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1201733779.902.18.camel>
