From owner-svn-src-head@FreeBSD.ORG Sun May 31 08:59:15 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F1E3A1065670; Sun, 31 May 2009 08:59:15 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D53F98FC0C; Sun, 31 May 2009 08:59:15 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n4V8xF7n036299; Sun, 31 May 2009 08:59:15 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4V8xFsq036297; Sun, 31 May 2009 08:59:15 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <200905310859.n4V8xFsq036297@svn.freebsd.org> From: Nathan Whitehorn Date: Sun, 31 May 2009 08:59:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r193155 - in head/sys: kern sys X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 31 May 2009 08:59:16 -0000 Author: nwhitehorn Date: Sun May 31 08:59:15 2009 New Revision: 193155 URL: http://svn.freebsd.org/changeset/base/193155 Log: Provide a new CPU device driver ivar to report the nominal speed of the CPU, if available. This is meant to solve the issue of cpufreq misreporting speeds on CPUs that boot in a reduced power mode and have only relative speed control. Modified: head/sys/kern/kern_cpu.c head/sys/sys/cpu.h Modified: head/sys/kern/kern_cpu.c ============================================================================== --- head/sys/kern/kern_cpu.c Sun May 31 08:11:39 2009 (r193154) +++ head/sys/kern/kern_cpu.c Sun May 31 08:59:15 2009 (r193155) @@ -158,12 +158,16 @@ 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 current CPU freq to use it as maximum later if needed */ - 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; + /* 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; + } /* * Only initialize one set of sysctls for all CPUs. In the future, @@ -581,15 +585,20 @@ cf_levels_method(device_t dev, struct cf /* * If there are no absolute levels, create a fake one at 100%. We * then cache the clockrate for later use as our base frequency. - * - * XXX This assumes that the first time through, if we only have - * relative drivers, the CPU is currently running at 100%. */ if (TAILQ_EMPTY(&sc->all_levels)) { if (sc->max_mhz == CPUFREQ_VAL_UNKNOWN) { - pc = cpu_get_pcpu(dev); - cpu_est_clockrate(pc->pc_cpuid, &rate); - sc->max_mhz = rate / 1000000; + sc->max_mhz = cpu_get_nominal_mhz(dev); + /* + * If the CPU can't report a rate for 100%, hope + * the CPU is running at its nominal rate right now, + * and use that instead. + */ + if (sc->max_mhz <= 0) { + pc = cpu_get_pcpu(dev); + cpu_est_clockrate(pc->pc_cpuid, &rate); + sc->max_mhz = rate / 1000000; + } } memset(&sets[0], CPUFREQ_VAL_UNKNOWN, sizeof(*sets)); sets[0].freq = sc->max_mhz; Modified: head/sys/sys/cpu.h ============================================================================== --- head/sys/sys/cpu.h Sun May 31 08:11:39 2009 (r193154) +++ head/sys/sys/cpu.h Sun May 31 08:59:15 2009 (r193155) @@ -36,6 +36,7 @@ */ #define CPU_IVAR_PCPU 1 +#define CPU_IVAR_NOMINAL_MHZ 2 static __inline struct pcpu *cpu_get_pcpu(device_t dev) { @@ -44,6 +45,15 @@ static __inline struct pcpu *cpu_get_pcp return ((struct pcpu *)v); } +static __inline int32_t cpu_get_nominal_mhz(device_t dev) +{ + uintptr_t v = 0; + if (BUS_READ_IVAR(device_get_parent(dev), dev, + CPU_IVAR_NOMINAL_MHZ, &v) != 0) + return (-1); + return ((int32_t)v); +} + /* * CPU frequency control interface. */