Module Name: src Committed By: jmcneill Date: Fri Jan 31 12:29:19 UTC 2025
Modified Files: src/sys/dev/acpi: acpi_cppc.c Log Message: acpi: cppc: Use frequency instead of performance units in sysctl interface. When possible, use frequency instead of abstract performance units in the sysctl interface. To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/dev/acpi/acpi_cppc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/acpi_cppc.c diff -u src/sys/dev/acpi/acpi_cppc.c:1.2 src/sys/dev/acpi/acpi_cppc.c:1.3 --- src/sys/dev/acpi/acpi_cppc.c:1.2 Fri Jan 29 15:49:55 2021 +++ src/sys/dev/acpi/acpi_cppc.c Fri Jan 31 12:29:19 2025 @@ -1,4 +1,4 @@ -/* $NetBSD: acpi_cppc.c,v 1.2 2021/01/29 15:49:55 thorpej Exp $ */ +/* $NetBSD: acpi_cppc.c,v 1.3 2025/01/31 12:29:19 jmcneill Exp $ */ /*- * Copyright (c) 2020 Jared McNeill <jmcne...@invisible.ca> @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: acpi_cppc.c,v 1.2 2021/01/29 15:49:55 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: acpi_cppc.c,v 1.3 2025/01/31 12:29:19 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -89,6 +89,8 @@ struct cppc_softc { int sc_node_current; ACPI_INTEGER sc_max_target; ACPI_INTEGER sc_min_target; + u_int sc_freq_range; + u_int sc_perf_range; }; static int cppc_match(device_t, cfdata_t, void *); @@ -195,6 +197,23 @@ cppc_parse_cpc(struct cppc_softc *sc) } /* + * cppc_perf_to_freq, cppc_freq_to_perf -- + * + * Convert between abstract performance values and CPU frequencies, + * when possible. + */ +static ACPI_INTEGER +cppc_perf_to_freq(struct cppc_softc *sc, ACPI_INTEGER perf) +{ + return howmany(perf * sc->sc_freq_range, sc->sc_perf_range); +} +static ACPI_INTEGER +cppc_freq_to_perf(struct cppc_softc *sc, ACPI_INTEGER freq) +{ + return howmany(freq * sc->sc_perf_range, sc->sc_freq_range); +} + +/* * cppc_cpufreq_sysctl -- * * sysctl helper function for machdep.cpu.cpuN.{target,current} @@ -229,7 +248,7 @@ cppc_cpufreq_sysctl(SYSCTLFN_ARGS) if (val > UINT32_MAX) { return ERANGE; } - fq = (u_int)val; + fq = (u_int)cppc_perf_to_freq(sc, val); if (rnode->sysctl_num == sc->sc_node_target) { oldfq = fq; @@ -248,7 +267,8 @@ cppc_cpufreq_sysctl(SYSCTLFN_ARGS) return EINVAL; } - rv = cppc_write(sc, CPCDesiredPerformanceReg, fq); + rv = cppc_write(sc, CPCDesiredPerformanceReg, + cppc_freq_to_perf(sc, fq)); if (ACPI_FAILURE(rv)) { return EIO; } @@ -270,7 +290,7 @@ cppc_cpufreq_init(struct cppc_softc *sc) CPCLowestNonlinearPerformance, CPCLowestPerformance }; - ACPI_INTEGER perf[4], last; + ACPI_INTEGER perf[4], min_freq = 0, nom_freq = 0, last; const struct sysctlnode *node, *cpunode; struct sysctllog *log = NULL; struct cpu_info *ci = sc->sc_cpuinfo; @@ -278,8 +298,31 @@ cppc_cpufreq_init(struct cppc_softc *sc) int error, i, n; /* + * Read optional nominal and lowest frequencies. These are used, + * when present, to scale units for display in the sysctl interface. + */ + cppc_read(sc, CPCLowestFrequency, &min_freq); + cppc_read(sc, CPCNominalFrequency, &nom_freq); + /* * Read highest, nominal, lowest nonlinear, and lowest performance - * levels and advertise this list of performance levels in the + * levels. + */ + for (i = 0, n = 0; i < __arraycount(perf_regs); i++) { + rv = cppc_read(sc, perf_regs[i], &perf[i]); + if (ACPI_FAILURE(rv)) { + return rv; + } + } + if (min_freq && nom_freq) { + sc->sc_freq_range = nom_freq - min_freq; + sc->sc_perf_range = perf[1] - perf[3]; + } else { + sc->sc_freq_range = 1; + sc->sc_perf_range = 1; + } + + /* + * Build a list of performance levels for the * machdep.cpufreq.cpuN.available sysctl. */ sc->sc_available = kmem_zalloc( @@ -293,14 +336,14 @@ cppc_cpufreq_init(struct cppc_softc *sc) if (perf[i] != last) { char buf[12]; snprintf(buf, sizeof(buf), n ? " %u" : "%u", - (u_int)perf[i]); + (u_int)cppc_perf_to_freq(sc, perf[i])); strcat(sc->sc_available, buf); last = perf[i]; n++; } } - sc->sc_max_target = perf[0]; - sc->sc_min_target = perf[3]; + sc->sc_max_target = cppc_perf_to_freq(sc, perf[0]); + sc->sc_min_target = cppc_perf_to_freq(sc, perf[3]); error = sysctl_createv(&log, 0, NULL, &node, CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,