From owner-freebsd-acpi@FreeBSD.ORG Fri Jan 4 14:55:51 2008 Return-Path: Delivered-To: freebsd-acpi@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE1D616A41B for ; Fri, 4 Jan 2008 14:55:51 +0000 (UTC) (envelope-from smithi@nimnet.asn.au) Received: from gaia.nimnet.asn.au (nimbin.lnk.telstra.net [139.130.45.143]) by mx1.freebsd.org (Postfix) with ESMTP id 8005413C45A for ; Fri, 4 Jan 2008 14:55:48 +0000 (UTC) (envelope-from smithi@nimnet.asn.au) Received: from localhost (smithi@localhost) by gaia.nimnet.asn.au (8.8.8/8.8.8R1.5) with SMTP id BAA08964; Sat, 5 Jan 2008 01:55:27 +1100 (EST) (envelope-from smithi@nimnet.asn.au) Date: Sat, 5 Jan 2008 01:55:26 +1100 (EST) From: Ian Smith To: Rui Paulo In-Reply-To: <86ejdaepm9.wl%rpaulo@fnop.net> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Cc: freebsd-acpi@freebsd.org Subject: Re: powerd doesn't decrease CPU frequency in some cases X-BeenThere: freebsd-acpi@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: ACPI and power management development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Jan 2008 14:55:51 -0000 On Tue, 25 Dec 2007, Rui Paulo wrote: > At Tue, 25 Dec 2007 17:16:58 +1100 (EST), > Ian Smith wrote: > > > > On Mon, 24 Dec 2007, Rui Paulo wrote: > > > At Mon, 24 Dec 2007 23:16:54 +0200, > > > Aragon Gouveia wrote: > > > > > > > > Hi, > > > > > > > > | By Rui Paulo > > > > | [ 2007-12-24 14:43 +0200 ] > > > > > Isn't it better to teach est(4) to ignore values that differ in, say, > > > > > +/- 5Mhz ? > > > > > > > > I agree my patch isn't ideal. I was thinking about it today and it might > > > > be useful to implement something that ignores frequencies whose power > > > > ratings don't differ by more than X mW. In my case, both 2201 and 2200 are > > > > rated to draw 35000 mW. The question is, in these cases which one of the > > > > two should be ignored? Can't ignore both... > > > > > > I think you can ignore one of them, which one doesn't really matter > > > because the power levels are the same. I suspect that, in these cases, > > > the 2001 comes after 2000 in the EST table, so if we ignore a value > > > already present, 2000 will remain and 2001 will be ignored. > > > > I'm starting to wonder if this 2000/2001 thing isn't some sort of signal > > to a Certain OS to do Something Proprietary. As it makes no engineering > > sense, best we can do for powerd without Inside Knowledge is what both > > these patches offer, eliminating/ignoring frequencies that won't set. > > > > It seems it does matter which is chosen; Andrey demonstrated in his case > > that setting 2000 gave 2001 anyway, so the one that reads back wrong > > when set is the one to ignore. It'd be better to know _why_, > > though. > > Well, the fact that "setting 2000 gave 2001 anyway" is most likely > regarding to how est is programmed, I think. Are we certain yet that this (apparently recent) 2001|2000 or 2201|2200 freq phenomenon only appears on hardware that uses est specifically? Trying to marginally reduce my ignorance I've done a bit of digging, not necessarily in this order .. % find /sys/ -name "*.[ch]" -exec egrep -Hi 'CPUFREQ_[GS]ET' {} \; /sys/kern/kern_cpu.c:static int cpufreq_settings_sysctl(SYSCTL_HANDLER_ARGS); /sys/kern/kern_cpu.c: DEVMETHOD(cpufreq_set, cf_set_method), /sys/kern/kern_cpu.c: DEVMETHOD(cpufreq_get, cf_get_method), /sys/kern/kern_cpu.c: error = CPUFREQ_GET(sc->dev, &levels[0]); /sys/kern/kern_cpu.c: * While we only call cpufreq_get() on one device (assuming all /sys/kern/kern_cpu.c: * CPUs have equal levels), we call cpufreq_set() on all CPUs. /sys/kern/kern_cpu.c: error = CPUFREQ_SET(devs[n], &levels[i], /sys/kern/kern_cpu.c:cpufreq_settings_sysctl(SYSCTL_HANDLER_ARGS) /sys/kern/kern_cpu.c: cpufreq_settings_sysctl, "A", "CPU frequency driver settings"); /sys/sys/cpu.h: * is registered, it must support calls to its CPUFREQ_GET, CPUFREQ_GET_LEVEL, /sys/sys/cpu.h: * and CPUFREQ_SET methods. It must also unregister before returning from So this seems where the main business is done. Up till then I'd been hunting through just /sys/dev/acpica/* and /sys/i386/cpufreq/* so this alone was a useful revelation. From that hunt derives this fat list: % find /sys/ -name "*.[ch]" -exec grep -Hi CPUFREQ_ {} \; and from there, it seems that only est.c does not use CPUFREQ_CMP(): % find /sys/ -name "*.[ch]" -exec grep -H CPUFREQ_CMP {} \; /sys/dev/acpica/acpi_perf.c: if (CPUFREQ_CMP(set->freq, sc->px_states[i].core_freq)) /sys/dev/acpica/acpi_perf.c: if (CPUFREQ_CMP(sc->px_states[i].core_freq, rate)) { /sys/dev/cpufreq/ichss.c: if (CPUFREQ_CMP(set->freq, sc->sets[0].freq)) /sys/dev/cpufreq/ichss.c: else if (CPUFREQ_CMP(set->freq, sc->sets[1].freq)) /sys/i386/cpufreq/powernow.c: if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq)) /sys/i386/cpufreq/smist.c: if (CPUFREQ_CMP(set->freq, sc->sets[0].freq)) /sys/i386/cpufreq/smist.c: else if (CPUFREQ_CMP(set->freq, sc->sets[1].freq)) /sys/kern/kern_cpu.c: if (CPUFREQ_CMP(sc->curr_level.total_set.freq, level->total_set.freq)) { /sys/kern/kern_cpu.c: if (CPUFREQ_CMP(set.freq, levels[i].total_set.freq)) { /sys/kern/kern_cpu.c: if (CPUFREQ_CMP(rate, levels[i].total_set.freq)) { /sys/kern/kern_cpu.c: if (CPUFREQ_CMP(fill_set->freq, itr_set->freq)) { /sys/kern/kern_cpu.c: if (CPUFREQ_CMP(levels[i].total_set.freq, freq)) { /sys/sys/cpu.h:#define CPUFREQ_CMP(x, y) (abs((x) - (y)) < 25) So the finest granularity in differing freqs is 25. (caveat: 5.5-STABLE sources from months ago, but I did check cpu.h on HEAD still has that) It's not yet clear to me, due to my generally meagre knowledge of C in general and method passing, softc, callbacks and such in particular, whether est's get/set calls override or assist what kern_cpu.c is up to? Cheers, Ian