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,

Reply via email to