Date: Wed, 20 Jul 2011 19:28:34 -0400 From: Jung-uk Kim <jkim@FreeBSD.org> To: freebsd-stable@FreeBSD.org Cc: Callum Gibson <callumgibson@optusnet.com.au>, freebsd-amd64@freebsd.org Subject: Re: powernow regression in 8-STABLE Message-ID: <201107201928.54079.jkim@FreeBSD.org> In-Reply-To: <20110719112033.GA51765@omma.gibson.athome> References: <20110719112033.GA51765@omma.gibson.athome>
next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_1S2JOs5PZu1wWD6 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On Tuesday 19 July 2011 07:20 am, Callum Gibson wrote: > Hi, > I've just noticed and tracked down a regression in > x86/cpufreq/powernow.c (on amd64) which was first mentioned here: > > http://lists.freebsd.org/pipermail/freebsd-current/2011-March/02350 >9.html > > although no followup seems to have occurred. The above thread is irrelevant. It was an Intel processor. > Symptoms are that powerd stops working because the dev.cpu.0.freq > OID is no longer gettable nor settable. > > This seems to have been caused by the following revision: > http://svnweb.freebsd.org/base?view=3Drevision&revision=3D222148 > which was in turn an MFC of r221102, so I guess the problem exists > on -current as well, although I can't confirm that since I don't > run it. > > Reverting the change fixes the problem and powerd will work again. > Also other utilities, such as xacpim, work properly. > > I'm running a ML-40 Turion laptop (HP Compaq nx6125). =46rom your dmesg output, I see that the processor speed was not=20 calibrated properly. ML-40's max. core freq. is 2,200 MHz according=20 to its specification but it was probed at 2,282 MHz, which is too=20 high. I think that's the problem. Can you please try the attached=20 patch? Jung-uk Kim --Boundary-00=_1S2JOs5PZu1wWD6 Content-Type: text/plain; charset="iso-8859-1"; name="kern_cpu.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kern_cpu.diff" Index: sys/kern/kern_cpu.c =================================================================== --- sys/kern/kern_cpu.c (revision 224231) +++ sys/kern/kern_cpu.c (working copy) @@ -159,16 +159,21 @@ cpufreq_attach(device_t dev) CF_MTX_INIT(&sc->lock); sc->curr_level.total_set.freq = CPUFREQ_VAL_UNKNOWN; SLIST_INIT(&sc->saved_freq); - /* Try to get nominal CPU freq to use it as maximum later if needed */ - sc->max_mhz = cpu_get_nominal_mhz(dev); - /* If that fails, try to measure the current rate */ - if (sc->max_mhz <= 0) { - pc = cpu_get_pcpu(dev); - if (cpu_est_clockrate(pc->pc_cpuid, &rate) == 0) - sc->max_mhz = rate / 1000000; - else - sc->max_mhz = CPUFREQ_VAL_UNKNOWN; + if (sc->max_mhz == CPUFREQ_VAL_UNKNOWN) { + /* Try to get nominal CPU freq to use it as maximum later. */ + sc->max_mhz = cpu_get_nominal_mhz(dev); + /* If that fails, try to measure the current rate */ + if (sc->max_mhz <= 0) { + pc = cpu_get_pcpu(dev); + if (cpu_est_clockrate(pc->pc_cpuid, &rate) == 0) + sc->max_mhz = rate / 1000000; + else + sc->max_mhz = CPUFREQ_VAL_UNKNOWN; + } } + if (sc->max_mhz == CPUFREQ_VAL_UNKNOWN) + CF_DEBUG("unknown max frequency for %s\n", + device_get_nameunit(dev)); /* * Only initialize one set of sysctls for all CPUs. In the future, @@ -1001,7 +1006,9 @@ int cpufreq_register(device_t dev) { struct cpufreq_softc *sc; + struct cf_setting *sets; device_t cf_dev, cpu_dev; + int error, max, set_count, type; /* Add a sysctl to get each driver's settings separately. */ SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), @@ -1009,14 +1016,29 @@ cpufreq_register(device_t dev) OID_AUTO, "freq_settings", CTLTYPE_STRING | CTLFLAG_RD, dev, 0, cpufreq_settings_sysctl, "A", "CPU frequency driver settings"); + /* Get settings from the device and find maximum if possible. */ + max = CPUFREQ_VAL_UNKNOWN; + if (CPUFREQ_DRV_TYPE(dev, &type) == 0 && + (type & CPUFREQ_TYPE_MASK) == CPUFREQ_TYPE_ABSOLUTE) { + set_count = MAX_SETTINGS; + sets = malloc(set_count * sizeof(*sets), M_TEMP, M_NOWAIT); + if (sets != NULL) { + if (CPUFREQ_DRV_SETTINGS(dev, sets, &set_count) == 0 && + set_count > 0) + max = sets[0].freq; + free(sets, M_TEMP); + } + } + /* * Add only one cpufreq device to each CPU. Currently, all CPUs * must offer the same levels and be switched at the same time. */ cpu_dev = device_get_parent(dev); - if ((cf_dev = device_find_child(cpu_dev, "cpufreq", -1))) { + cf_dev = device_find_child(cpu_dev, "cpufreq", -1); + if (cf_dev != NULL) { sc = device_get_softc(cf_dev); - sc->max_mhz = CPUFREQ_VAL_UNKNOWN; + sc->max_mhz = max; return (0); } @@ -1025,8 +1047,12 @@ cpufreq_register(device_t dev) if (cf_dev == NULL) return (ENOMEM); device_quiet(cf_dev); - - return (device_probe_and_attach(cf_dev)); + error = device_probe(cf_dev); + if (error != 0) + return (error); + sc = device_get_softc(cf_dev); + sc->max_mhz = max; + return (device_attach(cf_dev)); } int --Boundary-00=_1S2JOs5PZu1wWD6--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107201928.54079.jkim>