Date: Sun, 11 Nov 2007 21:21:13 +0200 From: Aragon Gouveia <aragon@phat.za.net> To: freebsd-acpi@freebsd.org Subject: My recent powerd problem Message-ID: <20071111192113.GA23686@phat.za.net>
next in thread | raw e-mail | index | archive | help
--xHFwDpU9dbj6ez1V Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, I recently installed FreeBSD 7.0-BETA2 onto my new HP Pavilion dv2600 notebook. I've encountered a couple of hiccups with it and this is my report of one of them... For some reason powerd would not lower the CPU frequency of my 2.2 GHz Core 2 Duo when it was in adaptive mode. When I ran it with -v I noticed it'd endlessly try set the CPU frequency to 2200 when the machine idled. Here's why: dev.cpu.0.freq_levels: 2201/35000 2200/35000 1925/30625 1650/26250 1600/23000 1400/20125 1200/16000 1050/14000 900/12000 800/14000 700/12250 600/10500 500/8750 400/7000 300/5250 200/3500 100/1750 # sysctl -w dev.cpu.0.freq=2200 dev.cpu.0.freq: 2201 -> 2201 So when trying to set the frequency to 2200 it gets changed back to 2201. Powerd would endlessly try set 2200 but it'd stay at 2201. So I wrote a patch to powerd to detect this and remove a frequency if it was unable to set it. It is attached to this mail. Well the patch works great and powerd is functioning normally now. However, I'm not sure this is the best fix. I'd really like to know why dev.cpu.0.freq_levels has 2201 and 2200 listed, and more importantly why 2200 can't be set despite its listing. Could this be a problem with my ACPI? Would an AML mod fix it? Thanks, Aragon --xHFwDpU9dbj6ez1V Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="powerd-rmfreq.diff" --- powerd.c.orig 2007-06-13 21:05:11.000000000 +0200 +++ powerd.c 2007-11-10 23:59:09.000000000 +0200 @@ -79,6 +79,7 @@ static int read_usage_times(long *idle, long *total); static int read_freqs(int *numfreqs, int **freqs, int **power); +static void rm_freq(int *numfreqs, int rmfreq, int **freqs, int **power); static int set_freq(int freq); static void acline_init(void); static void acline_read(void); @@ -189,6 +190,41 @@ return (0); } +static void +rm_freq(int *numfreqs, int rmfreq, int **freqs, int **power) +{ + int i, j=0, newfreqs[(*numfreqs)-1], newpower[(*numfreqs)-1]; + + if (*numfreqs < 2) { + // nothing more we can do + free(*freqs); + free(*power); + errx(1, "No more CPU frequencies to set"); + } + + for (i=0; i<*numfreqs; i++) { + if (i == rmfreq) continue; + newfreqs[j] = (*freqs)[i]; + newpower[j] = (*power)[i]; + j++; + } + + free(*freqs); + free(*power); + (*numfreqs)--; + if ((*freqs = malloc(*numfreqs * sizeof(int))) == NULL) + err(1, "error removing CPU frequency"); + if ((*power = malloc(*numfreqs * sizeof(int))) == NULL) { + free(*freqs); + err(1, "error removing CPU frequency"); + } + + for (i=0; i<=j; i++) { + (*freqs)[i] = newfreqs[i]; + (*power)[i] = newpower[i]; + } +} + static int set_freq(int freq) { @@ -555,6 +591,13 @@ freqs[numfreqs - 1]); continue; } + if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) == 0) { + if (curfreq != freqs[numfreqs-1]) { + if (vflag) + printf("error setting CPU frequency %d, removing from list\n", freqs[numfreqs-1]); + rm_freq(&numfreqs, numfreqs-1, &freqs, &mwatts); + } + } } continue; } @@ -573,6 +616,13 @@ freqs[0]); continue; } + if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) == 0) { + if (curfreq != freqs[0]) { + if (vflag) + printf("error setting CPU frequency %d, removing from list\n", freqs[0]); + rm_freq(&numfreqs, 0, &freqs, &mwatts); + } + } } continue; } @@ -605,6 +655,15 @@ if (set_freq(freqs[i])) warn("error setting CPU frequency %d", freqs[i]); + // Check if it actually got set + len = sizeof(curfreq); + if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) == 0) { + if (curfreq != freqs[i]) { + if (vflag) + printf("error setting CPU frequency %d, removing from list\n", freqs[i]); + rm_freq(&numfreqs, i, &freqs, &mwatts); + } + } } else if (idle > (total * cpu_idle_mark) / 100 && curfreq > freqs[numfreqs - 1]) { i++; @@ -616,6 +675,15 @@ if (set_freq(freqs[i]) != 0) warn("error setting CPU frequency %d", freqs[i]); + // Check if it actually got set + len = sizeof(curfreq); + if (sysctl(freq_mib, 4, &curfreq, &len, NULL, 0) == 0) { + if (curfreq != freqs[i]) { + if (vflag) + printf("error setting CPU frequency %d, removing from list\n", freqs[i]); + rm_freq(&numfreqs, i, &freqs, &mwatts); + } + } } } free(freqs); --xHFwDpU9dbj6ez1V--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20071111192113.GA23686>