Browse Source

Add gpuclockctl to allow privilaged control of GPU parameters

Marc Di Luzio 6 years ago
parent
commit
8d4e9ac54e

+ 4 - 65
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;
 }

+ 64 - 0
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;
+}

+ 61 - 0
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 );

+ 76 - 0
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;
+}

+ 16 - 0
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,
+)

+ 11 - 0
data/com.feralinteractive.GameMode.policy.in

@@ -23,4 +23,15 @@
     <annotate key="org.freedesktop.policykit.exec.path">@LIBEXECDIR@/cpugovctl</annotate>
   </action>
 
+  <action id="com.feralinteractive.GameMode.gpu-helper">
+    <description>Modify the GPU clock statesr</description>
+    <message>Authentication is required to modify the GPU clock states</message>
+    <defaults>
+      <allow_any>no</allow_any>
+      <allow_inactive>no</allow_inactive>
+      <allow_active>yes</allow_active>
+    </defaults>
+    <annotate key="org.freedesktop.policykit.exec.path">@LIBEXECDIR@/gpuclockctl</annotate>
+  </action>
+
 </policyconfig>