diff --git a/daemon/gamemode-gpu.c b/daemon/gamemode-gpu.c
index 5bf86c9..386666f 100644
--- a/daemon/gamemode-gpu.c
+++ b/daemon/gamemode-gpu.c
@@ -37,69 +37,16 @@ POSSIBILITY OF SUCH DAMAGE.
#include "logging.h"
#include "daemon_config.h"
+#include "gpu-query.h"
// TODO
// Gather GPU type and information
-// Allow configuration file specifying of gpu info
+// Allow override of vendor and device
// Apply Nvidia GPU settings (CoolBits will be needed)
// Apply AMD GPU settings (Will need user changing pwm1_enable)
// Intel?
// Provide documentation on optimisations
-/* Enums for GPU vendors */
-enum GPUVendor {
- Vendor_Invalid = 0,
- Vendor_NVIDIA = 0x10de,
- Vendor_AMD = 0x1002,
- Vendor_Intel = 0x8086
-};
-
-/* Storage for static GPU info gathered at start */
-struct GameModeGPUInfo {
- enum GPUVendor vendor;
- int device; /* path to device, ie. /sys/class/drm/card#/ */
-
- long core; /* Core clock to apply */
- long mem; /* Mem clock to apply */
-};
-
-/**
- * Applies or removes Nvidia optimisations
- */
-static int apply_gpu_nvidia(const GameModeGPUInfo *info, bool apply)
-{
- if (!info)
- return 0;
-
- // Running these commands:
- // nvidia-settings -a '[gpu:0]/GPUMemoryTransferRateOffset[3]=1400'
- // nvidia-settings -a '[gpu:0]/GPUGraphicsClockOffset[3]=50'
- if (apply) {
- } else {
- }
-
- return 0;
-}
-
-/**
- * Applies or removes AMD optimisations
- */
-static int apply_gpu_amd(const GameModeGPUInfo *info, bool apply)
-{
- if (!info)
- return 0;
-
- // We'll want to set both the following:
- // core: device/pp_sclk_od (0%+ additional)
- // mem: device/pp_mclk_od (0%+ additional)
- // Guide from https://www.maketecheasier.com/overclock-amd-gpu-linux/
- if (apply) {
- } else {
- }
-
- return 0;
-}
-
/**
* Attempts to identify the current in use GPU information
*/
@@ -121,7 +68,7 @@ int game_mode_initialise_gpu(GameModeConfig *config, GameModeGPUInfo **info)
GameModeGPUInfo *new_info = malloc(sizeof(GameModeGPUInfo));
memset(new_info, 0, sizeof(GameModeGPUInfo));
- // TODO: Fill in the GPU info
+ // TODO: Fill in the GPU vendor and device
/* Load the config based on GPU */
switch (new_info->vendor) {
@@ -160,15 +107,7 @@ int game_mode_apply_gpu(const GameModeGPUInfo *info, bool apply)
if (!info)
return 0;
- switch (info->vendor) {
- case Vendor_NVIDIA:
- return apply_gpu_nvidia(info, apply);
- case Vendor_AMD:
- return apply_gpu_amd(info, apply);
- default:
- break;
- }
+ /* TODO Call gpuclockctl set */
- /* Unsupported GPU vendor, do nothing */
return 0;
}
diff --git a/daemon/gpu-query.c b/daemon/gpu-query.c
new file mode 100644
index 0000000..7bf515c
--- /dev/null
+++ b/daemon/gpu-query.c
@@ -0,0 +1,64 @@
+/*
+
+Copyright (c) 2017-2018, Feral Interactive
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Feral Interactive nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+#define _GNU_SOURCE
+
+#include "gpu-query.h"
+#include "logging.h"
+
+// NVIDIA
+// Running these commands:
+// nvidia-settings -a '[gpu:0]/GPUMemoryTransferRateOffset[3]=1400'
+// nvidia-settings -a '[gpu:0]/GPUGraphicsClockOffset[3]=50'
+
+// AMD
+// We'll want to set both the following:
+// core: device/pp_sclk_od (0%+ additional)
+// mem: device/pp_mclk_od (0%+ additional)
+// Guide from https://www.maketecheasier.com/overclock-amd-gpu-linux/
+
+/**
+ * Get the gpu state
+ * Populates the struct with the GPU info on the system
+ */
+int get_gpu_state( struct GameModeGPUInfo* info )
+{
+ return 0;
+}
+
+/**
+ * Set the gpu state based on input parameters
+ * Only works when run as root
+ */
+int set_gpu_state( struct GameModeGPUInfo* info )
+{
+ return 0;
+}
diff --git a/daemon/gpu-query.h b/daemon/gpu-query.h
new file mode 100644
index 0000000..cab5214
--- /dev/null
+++ b/daemon/gpu-query.h
@@ -0,0 +1,61 @@
+/*
+
+Copyright (c) 2017-2018, Feral Interactive
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Feral Interactive nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+#pragma once
+
+/* Enums for GPU vendors */
+enum GPUVendor {
+ Vendor_Invalid = 0,
+ Vendor_NVIDIA = 0x10de,
+ Vendor_AMD = 0x1002,
+ Vendor_Intel = 0x8086
+};
+
+/* Storage for GPU info*/
+struct GameModeGPUInfo {
+ enum GPUVendor vendor;
+ int device; /* path to device, ie. /sys/class/drm/card#/ */
+
+ long core; /* Core clock to apply */
+ long mem; /* Mem clock to apply */
+};
+
+/**
+ * Get the gpu state
+ * Populates the struct with the GPU info on the system
+ */
+int get_gpu_state( struct GameModeGPUInfo* info );
+
+/**
+ * Set the gpu state based on input parameters
+ * Only works when run as root
+ */
+int set_gpu_state( struct GameModeGPUInfo* info );
diff --git a/daemon/gpuclockctl.c b/daemon/gpuclockctl.c
new file mode 100644
index 0000000..f954815
--- /dev/null
+++ b/daemon/gpuclockctl.c
@@ -0,0 +1,76 @@
+/*
+
+Copyright (c) 2017-2018, Feral Interactive
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Feral Interactive nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+#define _GNU_SOURCE
+
+#include "logging.h"
+
+#include "gpu-query.h"
+
+/**
+ * Main entry point, dispatch to the appropriate helper
+ */
+int main(int argc, char *argv[])
+{
+ if (argc == 4 && strncmp(argv[1], "get", 3) == 0) {
+ const char *vendor = argv[1];
+ const char *device = argv[2];
+
+ struct GameModeGPUInfo info;
+ /* TODO Populate with vendor and device */
+
+ get_gpu_state(&info);
+
+ printf("%d %d\n", info.core, info.mem);
+
+ } else if (argc == 6 && strncmp(argv[3], "set", 3) == 0) {
+ const char *vendor = argv[1];
+ const char *device = argv[2];
+ const char *core = argv[4];
+ const char *mem = argv[5];
+
+ /* Must be root to set the state */
+ if (geteuid() != 0) {
+ fprintf(stderr, "This program must be run as root\n");
+ return EXIT_FAILURE;
+ }
+
+ struct GameModeGPUInfo info;
+ /* TODO Populate with vendor, device and clocks */
+
+ return set_gpu_state(&info);
+ } else {
+ fprintf(stderr, "usage: gpuclockctl PCI_ID DEVICE [get] [set CORE MEM]\n");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/daemon/meson.build b/daemon/meson.build
index f5b054a..9b79453 100644
--- a/daemon/meson.build
+++ b/daemon/meson.build
@@ -2,6 +2,7 @@
common_sources = [
'logging.c',
'governors-query.c',
+ 'gpu-query.c',
]
daemon_common = static_library(
@@ -62,3 +63,18 @@ cpugovctl = executable(
install: true,
install_dir: path_libexecdir,
)
+
+# Small target util to get and set gpu clocks values
+gpuclockctl_sources = [
+ 'gpuclockctl.c',
+]
+
+gpuclockctl = executable(
+ 'gpuclockctl',
+ sources: gpuclockctl_sources,
+ dependencies: [
+ link_daemon_common,
+ ],
+ install: true,
+ install_dir: path_libexecdir,
+)
diff --git a/data/com.feralinteractive.GameMode.policy.in b/data/com.feralinteractive.GameMode.policy.in
index 8165162..b0dce0d 100644
--- a/data/com.feralinteractive.GameMode.policy.in
+++ b/data/com.feralinteractive.GameMode.policy.in
@@ -23,4 +23,15 @@
@LIBEXECDIR@/cpugovctl
+
+ Modify the GPU clock statesr
+ Authentication is required to modify the GPU clock states
+
+ no
+ no
+ yes
+
+ @LIBEXECDIR@/gpuclockctl
+
+