Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 5 Jan 2008 01:55:26 +1100 (EST)
From:      Ian Smith <smithi@nimnet.asn.au>
To:        Rui Paulo <rpaulo@fnop.net>
Cc:        freebsd-acpi@freebsd.org
Subject:   Re: powerd doesn't decrease CPU frequency in some cases
Message-ID:  <Pine.BSF.3.96.1080105004312.21758C-100000@gaia.nimnet.asn.au>
In-Reply-To: <86ejdaepm9.wl%rpaulo@fnop.net>

next in thread | previous in thread | raw e-mail | index | archive | help
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 <rpaulo@fnop.net>
 > >  > > |                                          [ 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




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.1080105004312.21758C-100000>