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>
next in thread | raw e-mail | index | archive | help
--Boundary_(ID_OLdYpMB8W8sfobiJiGBw+Q) Content-type: text/plain; charset=UTF-8 Content-transfer-encoding: 8BIT 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 (Олександр Коваленко) --Boundary_(ID_OLdYpMB8W8sfobiJiGBw+Q) Content-type: text/x-patch; name=powerd.c.patch; charset=UTF-8 Content-transfer-encoding: 7BIT Content-disposition: attachment; filename=powerd.c.patch --- 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. --Boundary_(ID_OLdYpMB8W8sfobiJiGBw+Q)--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1201733779.902.18.camel>