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=revision&revision=222148 > 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). From your dmesg output, I see that the processor speed was not calibrated properly. ML-40's max. core freq. is 2,200 MHz according to its specification but it was probed at 2,282 MHz, which is too high. I think that's the problem. Can you please try the attached patch? Jung-uk Kim
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
_______________________________________________ freebsd-stable@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-stable To unsubscribe, send any mail to "freebsd-stable-unsubscr...@freebsd.org"