Download raw body.
cpu perfpolicy
This introduces a helper function for hw.perfpolicy that allows more
machine specific policies to be set.
On my laptop, there's also a fan policy. This affects performance, but
it's not really related to the existing hw.setperf mechanism. For
example, a "silent" fan setting and "high" CPU setting is reasonable.
Exactly what I want, in fact.
Fortunately, perfpolicy takes a string, which makes it flexible.
This uses two new optional functions to parse and append the policy.
hw.perfpolicy=silent,auto
Index: dev/acpi/acpiwmi.c
===================================================================
RCS file: /home/cvs/src/sys/dev/acpi/acpiwmi.c,v
diff -u -p -r1.5 acpiwmi.c
--- dev/acpi/acpiwmi.c 21 May 2025 02:18:29 -0000 1.5
+++ dev/acpi/acpiwmi.c 29 May 2025 01:15:42 -0000
@@ -311,6 +311,40 @@ asus_toggle(struct wmiasus *wh, int devi
asus_dev_set(wh, devid, *val | mask);
}
+struct wmiasus *wmi_asus_policy_cookie;
+/* xxx the order may vary by machine... */
+static const char *asus_policies[] = { "standard,", "silent,", "perf," };
+
+void
+wmi_asus_setpolicy(char *policy)
+{
+ struct wmiasus *wh = wmi_asus_policy_cookie;
+ int target = -1;
+
+ for (int i = 0; i < nitems(asus_policies); i++) {
+ size_t len = strlen(asus_policies[i]);
+ if (strncmp(policy, asus_policies[i], len) == 0) {
+ target = i;
+ memmove(policy, policy + len, strlen(policy + len)+1);
+ break;
+ }
+ }
+ if (target != -1) {
+ wh->w_perf = target;
+ asus_dev_set(wh, wh->w_perfid, wh->w_perf);
+ }
+}
+
+void
+wmi_asus_getpolicy(char *policy, size_t len)
+{
+ struct wmiasus *wh = wmi_asus_policy_cookie;
+ int target = wh->w_perf;
+
+ if (target >= 0 && target < nitems(asus_policies))
+ strlcpy(policy, asus_policies[target], len);
+}
+
static int
wmi_asus_init(struct acpiwmi_softc *sc, struct guidinfo *ginfo)
{
@@ -342,6 +376,13 @@ wmi_asus_init(struct acpiwmi_softc *sc,
res = asus_dev_get(wh, ASUS_DEV_PERF_2);
if (res >= 0)
wh->w_perfid = ASUS_DEV_PERF_2;
+ if (wh->w_perfid != 0) {
+ extern void (*cpu_setpolicy)(char *);
+ extern void (*cpu_getpolicy)(char *, size_t);
+ cpu_getpolicy = wmi_asus_getpolicy;
+ cpu_setpolicy = wmi_asus_setpolicy;
+ wmi_asus_policy_cookie = wh;
+ }
// turn on by default
asus_toggle(wh, ASUS_DEV_KBDLIGHT, &wh->w_kbdlight);
Index: kern/sched_bsd.c
===================================================================
RCS file: /home/cvs/src/sys/kern/sched_bsd.c,v
diff -u -p -r1.100 sched_bsd.c
--- kern/sched_bsd.c 31 May 2025 06:58:27 -0000 1.100
+++ kern/sched_bsd.c 1 Jun 2025 07:48:21 -0000
@@ -541,6 +541,8 @@ schedclock(struct proc *p)
}
void (*cpu_setperf)(int);
+void (*cpu_setpolicy)(char *);
+void (*cpu_getpolicy)(char *, size_t);
#define PERFPOL_MANUAL 0
#define PERFPOL_AUTO 1
@@ -671,18 +673,22 @@ sysctl_hwperfpolicy(void *oldp, size_t *
if (!cpu_setperf)
return EOPNOTSUPP;
+ policy[0] = 0;
+ if (cpu_getpolicy)
+ cpu_getpolicy(policy, sizeof(policy));
+
switch (current_perfpolicy()) {
case PERFPOL_MANUAL:
- strlcpy(policy, "manual", sizeof(policy));
+ strlcat(policy, "manual", sizeof(policy));
break;
case PERFPOL_AUTO:
- strlcpy(policy, "auto", sizeof(policy));
+ strlcat(policy, "auto", sizeof(policy));
break;
case PERFPOL_HIGH:
- strlcpy(policy, "high", sizeof(policy));
+ strlcat(policy, "high", sizeof(policy));
break;
default:
- strlcpy(policy, "unknown", sizeof(policy));
+ strlcat(policy, "unknown", sizeof(policy));
break;
}
@@ -692,6 +698,9 @@ sysctl_hwperfpolicy(void *oldp, size_t *
err = sysctl_string(oldp, oldlenp, newp, newlen, policy, sizeof(policy));
if (err)
return err;
+
+ if (cpu_setpolicy)
+ cpu_setpolicy(policy);
policy_on_battery = strchr(policy, ',');
if (policy_on_battery != NULL) {
cpu perfpolicy