random/patches/gpuperf.diff
2024-05-10 13:31:11 +02:00

331 lines
9.6 KiB
Diff

This will throttle down your intel graphic card for
better thermal management.
It is bound to CPU performance settings via
hw.setperf sysctl.
Main Test Machine
cpu0: Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz, 2492.32 MHz, 06-2a-07
inteldrm0 at pci0 dev 2 function 0 "Intel HD Graphics 3000" rev 0x09
CPU 800MHz to 2500MHz
GPU 650MHz to 1300MHz
Secondary Test Machine
cpu0: Intel(R) Core(TM) i3-9100 CPU @ 3.60GHz, 3593.36 MHz, 06-9e-0b
inteldrm0 at pci0 dev 2 function 0 "Intel UHD Graphics 630" rev 0x00
CPU autothrottle -> GPU autothrottle (i.e 650MHz - 1300MHz)
CPU perf = 100 -> GPU throttle to max. frequency (i.e. 1300MHz)
CPU perf < 100 -> GPU throttle to base frequency (i.e. 650MHz)
Patch Version 8
Adapt for new DRM code (OpenBSD 6.7-current)
Patch Version 7
Header shuffling
Cleanup
Patch Version 6
Don't include in SMALL_KERNEL
Copyright update
Disable DEBUG output
Patch apply directions have changed
Patch Version 5
Cleanup
Patch Version 4
Switch from percentage to performance groups (LOW, HIGH, AUTO)
Cleanup
Patch Version 3
No longer implements a own sysctl
Patch apply directions have changed
Patch Version 2
Patch apply directions have changed
Includes man page change
Header cleanup
Patch Version 1
Throttle down to base freq on haswell & broadwell
Remove sensors, use debug printf
Patch Version 0
Initial POC
Using sensors framework only for debug
Only implemented for intel graphic
To apply:
cd /usr/src/sys && patch < gpuperf.diff
Rebuild and install a new kernel:
KK=`sysctl -n kern.osversion | cut -d# -f1`
cd /usr/src/sys/arch/`machine`/compile/$KK
make obj
make config
make
make install
Feedback and questions: programmer@netzbasis.de
Index: conf/files
===================================================================
RCS file: /var/cvs/src/sys/conf/files,v
retrieving revision 1.690
diff -u -p -r1.690 files
--- conf/files 6 Jul 2020 04:09:46 -0000 1.690
+++ conf/files 18 Jul 2020 19:43:06 -0000
@@ -717,6 +717,7 @@ file kern/subr_autoconf.c
file kern/subr_disk.c
file kern/subr_evcount.c
file kern/subr_extent.c
+file kern/subr_gpuperf.c !small_kernel
file kern/subr_hibernate.c hibernate
file kern/subr_kubsan.c kubsan
file kern/subr_log.c
Index: dev/pci/drm/i915/i915_drv.c
===================================================================
RCS file: /var/cvs/src/sys/dev/pci/drm/i915/i915_drv.c,v
retrieving revision 1.132
diff -u -p -r1.132 i915_drv.c
--- dev/pci/drm/i915/i915_drv.c 28 Jun 2020 02:29:19 -0000 1.132
+++ dev/pci/drm/i915/i915_drv.c 18 Jul 2020 19:46:36 -0000
@@ -2605,12 +2605,70 @@ inteldrm_attachhook(struct device *self)
config_found_sm(self, &aa, wsemuldisplaydevprint,
wsemuldisplaydevsubmatch);
+
+#ifdef __OpenBSD__
+ gpuperf_register(dev_priv->sc_dev.dv_xname,
+ inteldrm_set_gpuperf, dev_priv);
+#endif /* __OpenBSD__ */
+
return;
fail:
inteldrm_fatal_error = 1;
inteldrm_forcedetach(dev_priv);
}
+
+#ifdef __OpenBSD__
+#ifdef GPUPERF_DEBUG
+#define GPRINTF(x...) do { printf(x); } while(0)
+#else
+#define GPRINTF(x...)
+#endif /* GPUPERF_DEBUG */
+
+int
+inteldrm_set_gpuperf(gpuperf_level level, void *arg)
+{
+ struct inteldrm_softc *dev_priv = arg;
+ struct intel_rps *rps = &dev_priv->gt.rps;
+ u_int32_t min = rps->min_freq;
+ u_int32_t max = rps->max_freq;
+
+ GPRINTF("inteldrm: min %u, max %u, min_s %u, max_s %u, b %u, act %d MHz\n",
+ min, max, rps->min_freq_softlimit, rps->max_freq_softlimit,
+ rps->boost_freq, intel_gpu_freq(dev_priv, rps->cur_freq));
+
+ /*
+ * On haswell & broadwell min_freq_softlimit is higher than min_freq
+ * by default. Allow those devices to clock down further by ignoring
+ * this special case.
+ */
+ switch (level) {
+ case GPU_AUTO:
+ rps->max_freq_softlimit = max;
+ rps->boost_freq = max;
+ rps->min_freq_softlimit = min;
+ break;
+ case GPU_LOW:
+ rps->max_freq_softlimit = min;
+ rps->boost_freq = min;
+ rps->min_freq_softlimit = min;
+ break;
+ case GPU_HIGH:
+ rps->max_freq_softlimit = max;
+ rps->boost_freq = max;
+ rps->min_freq_softlimit = max;
+ break;
+ default:
+ return 1;
+ }
+
+ GPRINTF("inteldrm: min %u, max %u, min_s %u, max_s %u, b %u, act %d MHz\n",
+ min, max, rps->min_freq_softlimit, rps->max_freq_softlimit,
+ rps->boost_freq, intel_gpu_freq(dev_priv, rps->cur_freq));
+
+ return 0;
+}
+#endif /* __OpenBSD__ */
int
inteldrm_detach(struct device *self, int flags)
Index: dev/pci/drm/i915/i915_drv.h
===================================================================
RCS file: /var/cvs/src/sys/dev/pci/drm/i915/i915_drv.h,v
retrieving revision 1.92
diff -u -p -r1.92 i915_drv.h
--- dev/pci/drm/i915/i915_drv.h 29 Jun 2020 04:13:30 -0000 1.92
+++ dev/pci/drm/i915/i915_drv.h 18 Jul 2020 19:43:06 -0000
@@ -2000,3 +2000,8 @@ i915_coherent_map_type(struct drm_i915_p
}
#endif
+
+#ifdef __OpenBSD__
+#include <sys/gpuperf.h>
+int inteldrm_set_gpuperf(gpuperf_level level, void *arg);
+#endif /* __OpenBSD__ */
Index: kern/sched_bsd.c
===================================================================
RCS file: /var/cvs/src/sys/kern/sched_bsd.c,v
retrieving revision 1.63
diff -u -p -r1.63 sched_bsd.c
--- kern/sched_bsd.c 30 May 2020 14:42:59 -0000 1.63
+++ kern/sched_bsd.c 18 Jul 2020 19:43:06 -0000
@@ -540,6 +540,7 @@ int perfpolicy = PERFPOL_MANUAL;
/*
* The code below handles CPU throttling.
*/
+#include <sys/gpuperf.h>
#include <sys/sysctl.h>
void setperf_auto(void *);
@@ -630,6 +631,11 @@ sysctl_hwsetperf(void *oldp, size_t *old
perflevel = newperf;
cpu_setperf(perflevel);
+ if (perflevel == 100)
+ gpuperf_set(GPU_HIGH);
+ else
+ gpuperf_set(GPU_LOW);
+
return 0;
}
@@ -674,9 +680,11 @@ sysctl_hwperfpolicy(void *oldp, size_t *
if (perfpolicy == PERFPOL_AUTO) {
timeout_add_msec(&setperf_to, 200);
+ gpuperf_set(GPU_AUTO);
} else if (perfpolicy == PERFPOL_HIGH) {
perflevel = 100;
cpu_setperf(perflevel);
+ gpuperf_set(GPU_HIGH);
}
return 0;
}
Index: kern/subr_gpuperf.c
===================================================================
RCS file: kern/subr_gpuperf.c
diff -N kern/subr_gpuperf.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ kern/subr_gpuperf.c 18 Jul 2020 19:43:06 -0000
@@ -0,0 +1,79 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2019, 2020 Benjamin Baier <ben@netzbasis.de>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/gpuperf.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#ifdef GPUPERF_DEBUG
+#define DPRINTF(x...) do { printf(x); } while(0)
+#else
+#define DPRINTF(x...)
+#endif /* GPUPERF_DEBUG */
+
+struct gpuperf_dev {
+ char name[16]; /* device name */
+ void *arg; /* arg passthrough */
+ int (*callback)(gpuperf_level, void *);
+ LIST_ENTRY(gpuperf_dev) next;
+};
+
+LIST_HEAD(, gpuperf_dev) gpuperf_list =
+ LIST_HEAD_INITIALIZER(gpuperf_list);
+
+int
+gpuperf_register(const char *name, int (*callback)(gpuperf_level, void *),
+ void *arg)
+{
+ struct gpuperf_dev *dev;
+ int status = 0;
+
+ if ((dev = malloc(sizeof(*dev), M_DEVBUF, M_NOWAIT)) == NULL)
+ return -1;
+
+ strlcpy(dev->name, name, sizeof(dev->name));
+ dev->callback = callback;
+ dev->arg = arg;
+
+ LIST_INSERT_HEAD(&gpuperf_list, dev, next);
+ status = dev->callback(GPU_AUTO, dev->arg);
+
+ DPRINTF("gpuperf: %s registered, status %d\n", dev->name, status);
+
+ return status;
+}
+
+int
+gpuperf_set(gpuperf_level level)
+{
+ struct gpuperf_dev *dev;
+ int status = 0;
+
+ if ((level < GPU_AUTO) || (level > GPU_HIGH))
+ return -1;
+
+ LIST_FOREACH(dev, &gpuperf_list, next) {
+ status += dev->callback(level, dev->arg);
+
+ DPRINTF("gpuperf: requesting %d from %s, status %d\n",
+ level, dev->name, status);
+ }
+
+ return status;
+}
Index: sys/gpuperf.h
===================================================================
RCS file: sys/gpuperf.h
diff -N sys/gpuperf.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/gpuperf.h 18 Jul 2020 19:43:06 -0000
@@ -0,0 +1,31 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2019, 2020 Benjamin Baier <ben@netzbasis.de>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _SYS_GPUPERF_H_
+#define _SYS_GPUPERF_H_
+
+typedef enum {
+ GPU_AUTO,
+ GPU_LOW,
+ GPU_HIGH
+} gpuperf_level;
+
+int gpuperf_set(gpuperf_level);
+int gpuperf_register(const char *, int (*)(gpuperf_level, void *), void *);
+
+#endif /* _SYS_GPUPERF_H_ */