mirror of
https://github.com/terrapkg/packages.git
synced 2026-05-31 17:11:56 +00:00
6e4d8009a0
- for F42 the release was bumped to 8, needed to bump it again for the terra package to be updated to
- the discrete patch was updated to support the Intel Xe Driver
(cherry picked from commit f907735d06)
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
Co-authored-by: Jan <sentrycraft123@gmail.com>
1336 lines
38 KiB
Diff
1336 lines
38 KiB
Diff
From 44046bfbcb30a19c45416113a2a82a4d17a1a998 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Mon, 14 Aug 2023 14:06:45 +0200
|
|
Subject: [PATCH 01/13] main: update GPUs comment for dbus property
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
src/net.hadess.SwitcherooControl.xml | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/net.hadess.SwitcherooControl.xml b/src/net.hadess.SwitcherooControl.xml
|
|
index e52bc1a..59a8896 100644
|
|
--- a/src/net.hadess.SwitcherooControl.xml
|
|
+++ b/src/net.hadess.SwitcherooControl.xml
|
|
@@ -38,7 +38,8 @@
|
|
will contain a user-facing name for the GPU, the "Environment" (as) key will
|
|
contain an array of even number of strings, each being an environment
|
|
variable to set to use the GPU, followed by its value, the "Default" (b) key
|
|
- will tag the default (usually integrated) GPU.
|
|
+ will tag the default GPU, the "Discrete" (b) key tags if the GPU is a
|
|
+ dedicated component.
|
|
-->
|
|
<property name="GPUs" type="aa{sv}" access="read"/>
|
|
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 4f31415cb61a50c2bcba1510a7511518417d0970 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Mon, 11 Sep 2023 15:21:46 +0200
|
|
Subject: [PATCH 02/13] main: add Discrete key
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
.gitlab-ci.yml | 1 +
|
|
data/30-discrete-gpu.rules.in | 3 +
|
|
data/meson.build | 7 ++
|
|
meson.build | 9 +++
|
|
meson_options.txt | 24 +++++++
|
|
src/discrete-detection/amdgpu.c | 46 +++++++++++++
|
|
src/discrete-detection/meson.build | 18 +++++
|
|
src/discrete-detection/nouveau.c | 105 +++++++++++++++++++++++++++++
|
|
src/meson.build | 4 +-
|
|
src/switcheroo-control.c | 16 +++++
|
|
10 files changed, 232 insertions(+), 1 deletion(-)
|
|
create mode 100644 data/30-discrete-gpu.rules.in
|
|
create mode 100644 src/discrete-detection/amdgpu.c
|
|
create mode 100644 src/discrete-detection/meson.build
|
|
create mode 100644 src/discrete-detection/nouveau.c
|
|
|
|
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
|
|
index a6aa3c7..a09fe20 100644
|
|
--- a/.gitlab-ci.yml
|
|
+++ b/.gitlab-ci.yml
|
|
@@ -3,6 +3,7 @@ image: fedora:rawhide
|
|
variables:
|
|
DEPENDENCIES: glib2-devel
|
|
libgudev-devel
|
|
+ libdrm-devel
|
|
gtk-doc
|
|
gcc
|
|
gcc-c++
|
|
diff --git a/data/30-discrete-gpu.rules.in b/data/30-discrete-gpu.rules.in
|
|
new file mode 100644
|
|
index 0000000..a803ed4
|
|
--- /dev/null
|
|
+++ b/data/30-discrete-gpu.rules.in
|
|
@@ -0,0 +1,3 @@
|
|
+DRIVERS=="amdgpu", SUBSYSTEM=="drm", PROGRAM="@libexecdir@/check-discrete-amdgpu $env{DEVNAME}", TAG+="switcheroo-discrete-gpu"
|
|
+DRIVERS=="nouveau", SUBSYSTEM=="drm", PROGRAM="@libexecdir@/check-discrete-nouveau $env{DEVNAME}", TAG+="switcheroo-discrete-gpu"
|
|
+DRIVERS=="nvidia", TAG+="switcheroo-discrete-gpu"
|
|
diff --git a/data/meson.build b/data/meson.build
|
|
index 85e5c93..38cf96c 100644
|
|
--- a/data/meson.build
|
|
+++ b/data/meson.build
|
|
@@ -17,3 +17,10 @@ install_data(
|
|
'30-pci-intel-gpu.hwdb',
|
|
install_dir: hwdb_dir,
|
|
)
|
|
+
|
|
+configure_file(
|
|
+ input: '30-discrete-gpu.rules.in',
|
|
+ output: '30-discrete-gpu.rules',
|
|
+ configuration: data_conf,
|
|
+ install_dir: rules_dir,
|
|
+)
|
|
diff --git a/meson.build b/meson.build
|
|
index b8f4bff..b3aaf0c 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -20,6 +20,9 @@ gnome = import('gnome')
|
|
glib = dependency('glib-2.0', version: '>= 2.56.0')
|
|
gio = dependency('gio-2.0', version: '>= 2.56.0')
|
|
gudev = dependency('gudev-1.0', version: '>= 232')
|
|
+libdrm = dependency('libdrm', version: '>= 2.4.97', required: get_option('libdrm'))
|
|
+libdrm_nouveau = dependency('libdrm_nouveau', version: '>= 2.4.97', required: get_option('libdrm_nouveau'))
|
|
+libdrm_amdgpu = dependency('libdrm_amdgpu', version: '>= 2.4.97', required: get_option('libdrm_amdgpu'))
|
|
|
|
systemd_systemunitdir = get_option('systemdsystemunitdir')
|
|
if systemd_systemunitdir == ''
|
|
@@ -32,6 +35,12 @@ if hwdb_dir == ''
|
|
hwdb_dir = udevdir / 'hwdb.d'
|
|
endif
|
|
|
|
+rules_dir = get_option('rulesdir')
|
|
+if rules_dir == ''
|
|
+ udevdir = dependency('udev').get_pkgconfig_variable('udevdir')
|
|
+ rules_dir = udevdir / 'rules.d'
|
|
+endif
|
|
+
|
|
# Make like license available in the build root for docs
|
|
configure_file(
|
|
input: 'COPYING',
|
|
diff --git a/meson_options.txt b/meson_options.txt
|
|
index c8d9619..b8d671a 100644
|
|
--- a/meson_options.txt
|
|
+++ b/meson_options.txt
|
|
@@ -10,6 +10,12 @@ option('hwdbdir',
|
|
description: 'Directory for hwdb files',
|
|
)
|
|
|
|
+option('rulesdir',
|
|
+ type: 'string',
|
|
+ value: '',
|
|
+ description: 'Directory for ruke files',
|
|
+)
|
|
+
|
|
option('gtk_doc',
|
|
type: 'boolean',
|
|
value: false,
|
|
@@ -21,3 +27,21 @@ option('tests',
|
|
type: 'boolean',
|
|
value: false
|
|
)
|
|
+
|
|
+option('libdrm',
|
|
+ description: 'Whether libdrm should be used to probe GPUs',
|
|
+ type: 'feature',
|
|
+ value: 'auto'
|
|
+)
|
|
+
|
|
+option('libdrm_nouveau',
|
|
+ description: 'Whether libdrm_nouveau should be used to probe Nvidia GPUs',
|
|
+ type: 'feature',
|
|
+ value: 'auto'
|
|
+)
|
|
+
|
|
+option('libdrm_amdgpu',
|
|
+ description: 'Whether libdrm_amdgpu should be used to probe AMD GPUs',
|
|
+ type: 'feature',
|
|
+ value: 'auto'
|
|
+)
|
|
diff --git a/src/discrete-detection/amdgpu.c b/src/discrete-detection/amdgpu.c
|
|
new file mode 100644
|
|
index 0000000..2d9804f
|
|
--- /dev/null
|
|
+++ b/src/discrete-detection/amdgpu.c
|
|
@@ -0,0 +1,46 @@
|
|
+
|
|
+#include <fcntl.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdio.h>
|
|
+#include <gio/gio.h>
|
|
+#include <gudev/gudev.h>
|
|
+
|
|
+#include <amdgpu.h>
|
|
+#include <amdgpu_drm.h>
|
|
+
|
|
+typedef int handle;
|
|
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(handle, close, -1)
|
|
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(amdgpu_device_handle, free);
|
|
+
|
|
+int main(int argc, char** argv)
|
|
+{
|
|
+ if (argc < 2)
|
|
+ {
|
|
+ puts ("check-discrete-amdgpu [DEVNAME]");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ const char *devname;
|
|
+ g_auto(handle) fd = -1;
|
|
+ g_autoptr(GUdevDevice) parent = NULL;
|
|
+ struct drm_amdgpu_info_device device_info = {0};
|
|
+ amdgpu_device_handle device = NULL;
|
|
+ uint32_t drm_major, drm_minor;
|
|
+
|
|
+ devname = argv[1];
|
|
+ fd = open (devname, O_RDWR);
|
|
+ if (fd < 0)
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ if (amdgpu_device_initialize (fd, &drm_major, &drm_minor, &device))
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ if (amdgpu_query_info (device, AMDGPU_INFO_DEV_INFO, sizeof(device_info), &device_info))
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ /* AMDGPU_IDS_FLAGS_FUSION is set for all APUs */
|
|
+ if (device_info.ids_flags & AMDGPU_IDS_FLAGS_FUSION)
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ return EXIT_SUCCESS;
|
|
+}
|
|
diff --git a/src/discrete-detection/meson.build b/src/discrete-detection/meson.build
|
|
new file mode 100644
|
|
index 0000000..3a6c03f
|
|
--- /dev/null
|
|
+++ b/src/discrete-detection/meson.build
|
|
@@ -0,0 +1,18 @@
|
|
+
|
|
+if libdrm_amdgpu.found()
|
|
+ executable('check-discrete-amdgpu',
|
|
+ files('amdgpu.c'),
|
|
+ dependencies: deps,
|
|
+ install: true,
|
|
+ install_dir: libexecdir,
|
|
+ )
|
|
+endif
|
|
+
|
|
+if libdrm.found() and libdrm_nouveau.found()
|
|
+ executable('check-discrete-nouveau',
|
|
+ files('nouveau.c'),
|
|
+ dependencies: deps,
|
|
+ install: true,
|
|
+ install_dir: libexecdir,
|
|
+ )
|
|
+endif
|
|
diff --git a/src/discrete-detection/nouveau.c b/src/discrete-detection/nouveau.c
|
|
new file mode 100644
|
|
index 0000000..0a1f220
|
|
--- /dev/null
|
|
+++ b/src/discrete-detection/nouveau.c
|
|
@@ -0,0 +1,105 @@
|
|
+
|
|
+#include <fcntl.h>
|
|
+#include <stdlib.h>
|
|
+#include <stdio.h>
|
|
+#include <gio/gio.h>
|
|
+#include <gudev/gudev.h>
|
|
+
|
|
+#include <xf86drm.h>
|
|
+#include <nouveau_drm.h>
|
|
+#include <nouveau/nvif/ioctl.h>
|
|
+#include <nvif/cl0080.h>
|
|
+#include <nvif/class.h>
|
|
+
|
|
+typedef int handle;
|
|
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(handle, close, -1)
|
|
+
|
|
+int main(int argc, char** argv)
|
|
+{
|
|
+ if (argc < 2)
|
|
+ {
|
|
+ puts ("check-discrete-nouveau [DEVNAME]");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ const char *devname;
|
|
+ g_auto(handle) fd = -1;
|
|
+
|
|
+ devname = argv[1];
|
|
+ fd = open (devname, O_RDWR);
|
|
+ if (fd < 0)
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ g_autofree void *device = malloc(352);
|
|
+
|
|
+ /* Init device */
|
|
+ {
|
|
+ struct {
|
|
+ struct nvif_ioctl_v0 ioctl;
|
|
+ struct nvif_ioctl_new_v0 new;
|
|
+ struct nv_device_v0 dev;
|
|
+ } init_args = {
|
|
+ .ioctl = {
|
|
+ .object = 0,
|
|
+ .owner = NVIF_IOCTL_V0_OWNER_ANY,
|
|
+ .route = 0x00,
|
|
+ .type = NVIF_IOCTL_V0_NEW,
|
|
+ .version = 0,
|
|
+ },
|
|
+ .new = {
|
|
+ .handle = 0,
|
|
+ .object = (uintptr_t)device,
|
|
+ .oclass = NV_DEVICE,
|
|
+ .route = NVIF_IOCTL_V0_ROUTE_NVIF,
|
|
+ .token = (uintptr_t)device,
|
|
+ .version = 0,
|
|
+ },
|
|
+ .dev = {
|
|
+ .device = ~0ULL,
|
|
+ },
|
|
+ };
|
|
+
|
|
+ if (drmCommandWrite (fd, DRM_NOUVEAU_NVIF, &init_args, sizeof(init_args)))
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ /* Query device info */
|
|
+ struct {
|
|
+ struct nvif_ioctl_v0 ioctl;
|
|
+ struct nvif_ioctl_mthd_v0 mthd;
|
|
+ struct nv_device_info_v0 info;
|
|
+ } args = {
|
|
+ .ioctl = {
|
|
+ .object = (uintptr_t)device,
|
|
+ .owner = NVIF_IOCTL_V0_OWNER_ANY,
|
|
+ .route = 0x00,
|
|
+ .type = NVIF_IOCTL_V0_MTHD,
|
|
+ .version = 0,
|
|
+ },
|
|
+ .mthd = {
|
|
+ .method = NV_DEVICE_V0_INFO,
|
|
+ .version = 0,
|
|
+ },
|
|
+ .info = {
|
|
+ .version = 0,
|
|
+ },
|
|
+ };
|
|
+
|
|
+ if (drmCommandWriteRead (fd, DRM_NOUVEAU_NVIF, &args, sizeof(args)))
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+
|
|
+ switch (args.info.platform)
|
|
+ {
|
|
+ case NV_DEVICE_INFO_V0_IGP:
|
|
+ case NV_DEVICE_INFO_V0_SOC:
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ case NV_DEVICE_INFO_V0_PCI:
|
|
+ case NV_DEVICE_INFO_V0_AGP:
|
|
+ case NV_DEVICE_INFO_V0_PCIE:
|
|
+ default:
|
|
+ return EXIT_SUCCESS;
|
|
+ }
|
|
+ return EXIT_FAILURE;
|
|
+}
|
|
diff --git a/src/meson.build b/src/meson.build
|
|
index ab3a77d..da4267f 100644
|
|
--- a/src/meson.build
|
|
+++ b/src/meson.build
|
|
@@ -1,4 +1,4 @@
|
|
-deps = [glib, gio, gudev]
|
|
+deps = [glib, gio, gudev, libdrm, libdrm_nouveau, libdrm_amdgpu]
|
|
|
|
sources = [
|
|
'info-cleanup.c',
|
|
@@ -34,3 +34,5 @@ configure_file(
|
|
configuration: switcherooctl_conf,
|
|
install_dir: get_option('bindir')
|
|
)
|
|
+
|
|
+subdir('discrete-detection')
|
|
diff --git a/src/switcheroo-control.c b/src/switcheroo-control.c
|
|
index abd8154..e407bfb 100644
|
|
--- a/src/switcheroo-control.c
|
|
+++ b/src/switcheroo-control.c
|
|
@@ -31,6 +31,7 @@ typedef struct {
|
|
char *name;
|
|
GPtrArray *env;
|
|
gboolean is_default;
|
|
+ gboolean is_discrete;
|
|
} CardData;
|
|
|
|
typedef struct {
|
|
@@ -94,6 +95,8 @@ build_gpus_variant (ControlData *data)
|
|
g_variant_new_strv ((const gchar * const *) card->env->pdata, card->env->len));
|
|
g_variant_builder_add (&asv_builder, "{sv}", "Default",
|
|
g_variant_new_boolean (card->is_default));
|
|
+ g_variant_builder_add (&asv_builder, "{sv}", "Discrete",
|
|
+ g_variant_new_boolean (card->is_discrete));
|
|
|
|
g_variant_builder_add (&builder, "a{sv}", &asv_builder);
|
|
}
|
|
@@ -312,6 +315,18 @@ get_card_is_default (GUdevDevice *d)
|
|
return g_udev_device_get_sysfs_attr_as_boolean (parent, "boot_vga");
|
|
}
|
|
|
|
+static gboolean
|
|
+get_card_is_discrete (GUdevDevice *d)
|
|
+{
|
|
+ const char * const * tags;
|
|
+ g_autoptr (GUdevDevice) platform_device = NULL;
|
|
+
|
|
+ tags = g_udev_device_get_tags (d);
|
|
+ if (tags && g_strv_contains (tags, "switcheroo-discrete-gpu"))
|
|
+ return TRUE;
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
static CardData *
|
|
get_card_data (GUdevClient *client,
|
|
GUdevDevice *d)
|
|
@@ -328,6 +343,7 @@ get_card_data (GUdevClient *client,
|
|
data->name = get_card_name (d);
|
|
data->env = env;
|
|
data->is_default = get_card_is_default (d);
|
|
+ data->is_discrete = get_card_is_discrete (d);
|
|
|
|
return data;
|
|
}
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 1b115ed72e03ff1169cbfddd79ef10890baca133 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Tue, 12 Sep 2023 15:53:40 +0200
|
|
Subject: [PATCH 03/13] tests: fix integration tests without UMockdev
|
|
`gi.require_version` throws ValueError if the dependency cannot be found
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
tests/integration-test.py | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/tests/integration-test.py b/tests/integration-test.py
|
|
index d8dea16..e3dd996 100755
|
|
--- a/tests/integration-test.py
|
|
+++ b/tests/integration-test.py
|
|
@@ -37,7 +37,7 @@ except ImportError as e:
|
|
try:
|
|
gi.require_version('UMockdev', '1.0')
|
|
from gi.repository import UMockdev
|
|
-except ImportError:
|
|
+except (ImportError, ValueError):
|
|
sys.stderr.write('Skipping tests, umockdev not available (https://github.com/martinpitt/umockdev)\n')
|
|
sys.exit(0)
|
|
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From d933e96bdb15679ae7653f929461982aa66973ba Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Tue, 12 Sep 2023 15:58:16 +0200
|
|
Subject: [PATCH 04/13] tests: add tests for discrete detection with mock libs
|
|
Both tests have 4 different ways of testing: - Invalid Device - Unexpected
|
|
Device - Non Discrete GPU (iGPU/APU) - Discrete GPU
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
src/discrete-detection/meson.build | 4 +-
|
|
tests/discrete-detection/libdrm_amdgpu_mock.c | 57 +++++++++++++
|
|
.../discrete-detection/libdrm_nouveau_mock.c | 68 ++++++++++++++++
|
|
tests/discrete-detection/meson.build | 80 +++++++++++++++++++
|
|
tests/meson.build | 2 +
|
|
5 files changed, 209 insertions(+), 2 deletions(-)
|
|
create mode 100644 tests/discrete-detection/libdrm_amdgpu_mock.c
|
|
create mode 100644 tests/discrete-detection/libdrm_nouveau_mock.c
|
|
create mode 100644 tests/discrete-detection/meson.build
|
|
|
|
diff --git a/src/discrete-detection/meson.build b/src/discrete-detection/meson.build
|
|
index 3a6c03f..8eb8437 100644
|
|
--- a/src/discrete-detection/meson.build
|
|
+++ b/src/discrete-detection/meson.build
|
|
@@ -1,6 +1,6 @@
|
|
|
|
if libdrm_amdgpu.found()
|
|
- executable('check-discrete-amdgpu',
|
|
+ amdgpu_discrete = executable('check-discrete-amdgpu',
|
|
files('amdgpu.c'),
|
|
dependencies: deps,
|
|
install: true,
|
|
@@ -9,7 +9,7 @@ if libdrm_amdgpu.found()
|
|
endif
|
|
|
|
if libdrm.found() and libdrm_nouveau.found()
|
|
- executable('check-discrete-nouveau',
|
|
+ nouveau_discrete = executable('check-discrete-nouveau',
|
|
files('nouveau.c'),
|
|
dependencies: deps,
|
|
install: true,
|
|
diff --git a/tests/discrete-detection/libdrm_amdgpu_mock.c b/tests/discrete-detection/libdrm_amdgpu_mock.c
|
|
new file mode 100644
|
|
index 0000000..20fa4aa
|
|
--- /dev/null
|
|
+++ b/tests/discrete-detection/libdrm_amdgpu_mock.c
|
|
@@ -0,0 +1,57 @@
|
|
+#include <string.h>
|
|
+#include <stdint.h>
|
|
+#include <stdio.h>
|
|
+
|
|
+#include <amdgpu_drm.h>
|
|
+
|
|
+enum {
|
|
+ OTHER_GPU,
|
|
+ AMD_APU,
|
|
+ AMD_GPU,
|
|
+};
|
|
+
|
|
+/* Mock open(2) so we can test multiple devices configurations */
|
|
+int open(const char *pathname, int flags)
|
|
+{
|
|
+ if (!strcmp(pathname, "OTHER_GPU"))
|
|
+ return OTHER_GPU;
|
|
+ if (!strcmp (pathname, "AMD_APU"))
|
|
+ return AMD_APU;
|
|
+ if (!strcmp (pathname, "AMD_GPU"))
|
|
+ return AMD_GPU;
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/* open64 may be used for large file support */
|
|
+int open64(const char *pathname, int flags)
|
|
+{
|
|
+ return open (pathname, flags);
|
|
+}
|
|
+
|
|
+int amdgpu_device_initialize(int fd, uint32_t *major_version, uint32_t *minor_version, int *device_handle)
|
|
+{
|
|
+ // Store the fd in the device handle for access in query_info
|
|
+ *device_handle = fd;
|
|
+
|
|
+ if (fd != AMD_GPU && fd != AMD_APU)
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int amdgpu_query_info(int device_handle, unsigned info_id, unsigned size, void *value)
|
|
+{
|
|
+ struct drm_amdgpu_info_device* device_info = value;
|
|
+
|
|
+ if (device_handle == AMD_GPU) {
|
|
+ device_info->ids_flags = 0;
|
|
+ return 0;
|
|
+ }
|
|
+ if (device_handle == AMD_APU) {
|
|
+ device_info->ids_flags = AMDGPU_IDS_FLAGS_FUSION;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
diff --git a/tests/discrete-detection/libdrm_nouveau_mock.c b/tests/discrete-detection/libdrm_nouveau_mock.c
|
|
new file mode 100644
|
|
index 0000000..cdbfda8
|
|
--- /dev/null
|
|
+++ b/tests/discrete-detection/libdrm_nouveau_mock.c
|
|
@@ -0,0 +1,68 @@
|
|
+#include <string.h>
|
|
+#include <stdint.h>
|
|
+#include <stdio.h>
|
|
+
|
|
+#include <xf86drm.h>
|
|
+#include <nouveau_drm.h>
|
|
+#include <nouveau/nvif/ioctl.h>
|
|
+#include <nvif/cl0080.h>
|
|
+#include <nvif/class.h>
|
|
+
|
|
+enum {
|
|
+ OTHER_GPU,
|
|
+ NVIDIA_IGPU,
|
|
+ NVIDIA_GPU,
|
|
+};
|
|
+
|
|
+/* Mock open(2) so we can test multiple devices configurations */
|
|
+int open(const char *pathname, int flags)
|
|
+{
|
|
+ if (!strcmp(pathname, "OTHER_GPU"))
|
|
+ return OTHER_GPU;
|
|
+ if (!strcmp (pathname, "NVIDIA_IGPU"))
|
|
+ return NVIDIA_IGPU;
|
|
+ if (!strcmp (pathname, "NVIDIA_GPU"))
|
|
+ return NVIDIA_GPU;
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/* open64 may be used for large file support */
|
|
+int open64(const char *pathname, int flags)
|
|
+{
|
|
+ return open (pathname, flags);
|
|
+}
|
|
+
|
|
+int drmCommandWrite(int fd, unsigned long drmCommandIndex, void *data, unsigned long size)
|
|
+{
|
|
+ if (drmCommandIndex != DRM_NOUVEAU_NVIF)
|
|
+ return 1;
|
|
+
|
|
+ if (fd != NVIDIA_GPU && fd != NVIDIA_IGPU)
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int drmCommandWriteRead(int fd, unsigned long drmCommandIndex, void *data, unsigned long size)
|
|
+{
|
|
+ if (drmCommandIndex != DRM_NOUVEAU_NVIF)
|
|
+ return 1;
|
|
+
|
|
+ struct {
|
|
+ struct nvif_ioctl_v0 ioctl;
|
|
+ struct nvif_ioctl_mthd_v0 mthd;
|
|
+ struct nv_device_info_v0 info;
|
|
+ } *args = data;
|
|
+
|
|
+ if (fd == NVIDIA_GPU) {
|
|
+ args->info.platform = NV_DEVICE_INFO_V0_PCIE;
|
|
+ return 0;
|
|
+ }
|
|
+ if (fd == NVIDIA_IGPU) {
|
|
+ args->info.platform = NV_DEVICE_INFO_V0_IGP;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/tests/discrete-detection/meson.build b/tests/discrete-detection/meson.build
|
|
new file mode 100644
|
|
index 0000000..f01a014
|
|
--- /dev/null
|
|
+++ b/tests/discrete-detection/meson.build
|
|
@@ -0,0 +1,80 @@
|
|
+
|
|
+if libdrm_amdgpu.found()
|
|
+ amdgpu_mock_lib = shared_library(
|
|
+ 'drm_amdgpu_mock',
|
|
+ files('libdrm_amdgpu_mock.c'),
|
|
+ dependencies: libdrm_amdgpu
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test amdgpu detection with invalid device',
|
|
+ amdgpu_discrete,
|
|
+ args: ['NO_GPU'],
|
|
+ env: environment({'LD_PRELOAD': amdgpu_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test amdgpu detection with non-AMD GPU',
|
|
+ amdgpu_discrete,
|
|
+ args: ['OTHER_GPU'],
|
|
+ env: environment({'LD_PRELOAD': amdgpu_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test amdgpu detection with AMD APU',
|
|
+ amdgpu_discrete,
|
|
+ args: ['AMD_APU'],
|
|
+ env: environment({'LD_PRELOAD': amdgpu_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test amdgpu detection with AMD GPU',
|
|
+ amdgpu_discrete,
|
|
+ args: ['AMD_GPU'],
|
|
+ env: environment({'LD_PRELOAD': amdgpu_mock_lib.full_path()}),
|
|
+ should_fail: false
|
|
+ )
|
|
+endif
|
|
+
|
|
+if libdrm.found() and libdrm_nouveau.found()
|
|
+ nouveau_mock_lib = shared_library(
|
|
+ 'drm_nouveau_mock',
|
|
+ files('libdrm_nouveau_mock.c'),
|
|
+ dependencies: [libdrm, libdrm_nouveau]
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test nouveau detection with invalid device',
|
|
+ nouveau_discrete,
|
|
+ args: ['NO_GPU'],
|
|
+ env: environment({'LD_PRELOAD': nouveau_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test nouveau detection with non-Nvidia GPU',
|
|
+ nouveau_discrete,
|
|
+ args: ['OTHER_GPU'],
|
|
+ env: environment({'LD_PRELOAD': nouveau_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test nouveau detection with Nvidia iGPU',
|
|
+ nouveau_discrete,
|
|
+ args: ['NVIDIA_IGPU'],
|
|
+ env: environment({'LD_PRELOAD': nouveau_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test nouveau detection with Nvidia GPU',
|
|
+ nouveau_discrete,
|
|
+ args: ['NVIDIA_GPU'],
|
|
+ env: environment({'LD_PRELOAD': nouveau_mock_lib.full_path()}),
|
|
+ should_fail: false
|
|
+ )
|
|
+endif
|
|
\ No newline at end of file
|
|
diff --git a/tests/meson.build b/tests/meson.build
|
|
index b0b7476..61ef00c 100644
|
|
--- a/tests/meson.build
|
|
+++ b/tests/meson.build
|
|
@@ -15,3 +15,5 @@ foreach ut: unit_tests
|
|
env: envs,
|
|
)
|
|
endforeach
|
|
+
|
|
+subdir('discrete-detection')
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From c102b643945dc076d881497dd2ca5865938f7053 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Tue, 12 Sep 2023 15:57:47 +0200
|
|
Subject: [PATCH 05/13] main: remove leftover and fix typo
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
meson_options.txt | 2 +-
|
|
src/switcheroo-control.c | 1 -
|
|
2 files changed, 1 insertion(+), 2 deletions(-)
|
|
|
|
diff --git a/meson_options.txt b/meson_options.txt
|
|
index b8d671a..c77fea8 100644
|
|
--- a/meson_options.txt
|
|
+++ b/meson_options.txt
|
|
@@ -13,7 +13,7 @@ option('hwdbdir',
|
|
option('rulesdir',
|
|
type: 'string',
|
|
value: '',
|
|
- description: 'Directory for ruke files',
|
|
+ description: 'Directory for rule files',
|
|
)
|
|
|
|
option('gtk_doc',
|
|
diff --git a/src/switcheroo-control.c b/src/switcheroo-control.c
|
|
index e407bfb..0f6a548 100644
|
|
--- a/src/switcheroo-control.c
|
|
+++ b/src/switcheroo-control.c
|
|
@@ -319,7 +319,6 @@ static gboolean
|
|
get_card_is_discrete (GUdevDevice *d)
|
|
{
|
|
const char * const * tags;
|
|
- g_autoptr (GUdevDevice) platform_device = NULL;
|
|
|
|
tags = g_udev_device_get_tags (d);
|
|
if (tags && g_strv_contains (tags, "switcheroo-discrete-gpu"))
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From f764db4eb565c19ba14155791fbfced3fb5d34c8 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Tue, 12 Sep 2023 15:58:27 +0200
|
|
Subject: [PATCH 06/13] main: move discrete dependencies out of main deps
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
src/discrete-detection/meson.build | 5 +++--
|
|
src/meson.build | 2 +-
|
|
2 files changed, 4 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/discrete-detection/meson.build b/src/discrete-detection/meson.build
|
|
index 8eb8437..353316f 100644
|
|
--- a/src/discrete-detection/meson.build
|
|
+++ b/src/discrete-detection/meson.build
|
|
@@ -1,8 +1,9 @@
|
|
+discrete_deps = deps + [libdrm, libdrm_nouveau, libdrm_amdgpu]
|
|
|
|
if libdrm_amdgpu.found()
|
|
amdgpu_discrete = executable('check-discrete-amdgpu',
|
|
files('amdgpu.c'),
|
|
- dependencies: deps,
|
|
+ dependencies: discrete_deps,
|
|
install: true,
|
|
install_dir: libexecdir,
|
|
)
|
|
@@ -11,7 +12,7 @@ endif
|
|
if libdrm.found() and libdrm_nouveau.found()
|
|
nouveau_discrete = executable('check-discrete-nouveau',
|
|
files('nouveau.c'),
|
|
- dependencies: deps,
|
|
+ dependencies: discrete_deps,
|
|
install: true,
|
|
install_dir: libexecdir,
|
|
)
|
|
diff --git a/src/meson.build b/src/meson.build
|
|
index da4267f..22d69e7 100644
|
|
--- a/src/meson.build
|
|
+++ b/src/meson.build
|
|
@@ -1,4 +1,4 @@
|
|
-deps = [glib, gio, gudev, libdrm, libdrm_nouveau, libdrm_amdgpu]
|
|
+deps = [glib, gio, gudev]
|
|
|
|
sources = [
|
|
'info-cleanup.c',
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From d2ecc29469d5572fd171926c9d1dbb1b851c7b09 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Tue, 12 Sep 2023 17:12:00 +0200
|
|
Subject: [PATCH 07/13] main: use glib for discrete command-line arguments
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
src/discrete-detection/amdgpu.c | 29 ++++++++++++++++++++---------
|
|
src/discrete-detection/nouveau.c | 29 ++++++++++++++++++++---------
|
|
2 files changed, 40 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/src/discrete-detection/amdgpu.c b/src/discrete-detection/amdgpu.c
|
|
index 2d9804f..5a9a4ab 100644
|
|
--- a/src/discrete-detection/amdgpu.c
|
|
+++ b/src/discrete-detection/amdgpu.c
|
|
@@ -1,9 +1,10 @@
|
|
-
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
+#include <locale.h>
|
|
#include <gio/gio.h>
|
|
#include <gudev/gudev.h>
|
|
+#include <glib.h>
|
|
|
|
#include <amdgpu.h>
|
|
#include <amdgpu_drm.h>
|
|
@@ -12,22 +13,32 @@ typedef int handle;
|
|
G_DEFINE_AUTO_CLEANUP_FREE_FUNC(handle, close, -1)
|
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC(amdgpu_device_handle, free);
|
|
|
|
-int main(int argc, char** argv)
|
|
+int main (int argc, char** argv)
|
|
{
|
|
- if (argc < 2)
|
|
- {
|
|
- puts ("check-discrete-amdgpu [DEVNAME]");
|
|
- return EXIT_FAILURE;
|
|
- }
|
|
-
|
|
const char *devname;
|
|
g_auto(handle) fd = -1;
|
|
- g_autoptr(GUdevDevice) parent = NULL;
|
|
struct drm_amdgpu_info_device device_info = {0};
|
|
amdgpu_device_handle device = NULL;
|
|
uint32_t drm_major, drm_minor;
|
|
+ g_autoptr(GOptionContext) option_context = NULL;
|
|
+ g_autoptr(GError) error = NULL;
|
|
|
|
+ setlocale (LC_ALL, "");
|
|
+ option_context = g_option_context_new ("");
|
|
+
|
|
+ if (!g_option_context_parse (option_context, &argc, &argv, &error)) {
|
|
+ g_print ("Failed to parse arguments: %s\n", error->message);
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ if (argc < 2)
|
|
+ {
|
|
+ g_print ("%s\n", g_option_context_get_help (option_context, TRUE, NULL));
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
devname = argv[1];
|
|
+;
|
|
+
|
|
fd = open (devname, O_RDWR);
|
|
if (fd < 0)
|
|
return EXIT_FAILURE;
|
|
diff --git a/src/discrete-detection/nouveau.c b/src/discrete-detection/nouveau.c
|
|
index 0a1f220..1d61cbb 100644
|
|
--- a/src/discrete-detection/nouveau.c
|
|
+++ b/src/discrete-detection/nouveau.c
|
|
@@ -1,9 +1,10 @@
|
|
-
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
+#include <locale.h>
|
|
#include <gio/gio.h>
|
|
#include <gudev/gudev.h>
|
|
+#include <glib.h>
|
|
|
|
#include <xf86drm.h>
|
|
#include <nouveau_drm.h>
|
|
@@ -14,23 +15,34 @@
|
|
typedef int handle;
|
|
G_DEFINE_AUTO_CLEANUP_FREE_FUNC(handle, close, -1)
|
|
|
|
-int main(int argc, char** argv)
|
|
+int main (int argc, char** argv)
|
|
{
|
|
+ const gchar *devname = NULL;
|
|
+ g_auto(handle) fd = -1;
|
|
+ g_autofree void *device = NULL;
|
|
+ g_autoptr(GOptionContext) option_context = NULL;
|
|
+ g_autoptr(GError) error = NULL;
|
|
+
|
|
+ setlocale (LC_ALL, "");
|
|
+ option_context = g_option_context_new ("");
|
|
+
|
|
+ if (!g_option_context_parse (option_context, &argc, &argv, &error)) {
|
|
+ g_print ("Failed to parse arguments: %s\n", error->message);
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
if (argc < 2)
|
|
{
|
|
- puts ("check-discrete-nouveau [DEVNAME]");
|
|
+ g_print ("%s\n", g_option_context_get_help (option_context, TRUE, NULL));
|
|
return EXIT_FAILURE;
|
|
}
|
|
-
|
|
- const char *devname;
|
|
- g_auto(handle) fd = -1;
|
|
-
|
|
devname = argv[1];
|
|
+
|
|
fd = open (devname, O_RDWR);
|
|
if (fd < 0)
|
|
return EXIT_FAILURE;
|
|
|
|
- g_autofree void *device = malloc(352);
|
|
+ device = malloc(352);
|
|
|
|
/* Init device */
|
|
{
|
|
@@ -88,7 +100,6 @@ int main(int argc, char** argv)
|
|
if (drmCommandWriteRead (fd, DRM_NOUVEAU_NVIF, &args, sizeof(args)))
|
|
return EXIT_FAILURE;
|
|
|
|
-
|
|
switch (args.info.platform)
|
|
{
|
|
case NV_DEVICE_INFO_V0_IGP:
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 462b09f02de37dfd2965d23cc7c4137bcf45a4ae Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Wed, 14 Feb 2024 20:25:42 +0100
|
|
Subject: [PATCH 08/13] main: add udev rule for i915 checking a lot of systems
|
|
has shown that the intel iGPU will always be available at `0000:00:02.0`.
|
|
Using ID_PATH would have been cleaner, but I couldn't get it to work.
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
data/30-discrete-gpu.rules.in | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/data/30-discrete-gpu.rules.in b/data/30-discrete-gpu.rules.in
|
|
index a803ed4..f30f315 100644
|
|
--- a/data/30-discrete-gpu.rules.in
|
|
+++ b/data/30-discrete-gpu.rules.in
|
|
@@ -1,3 +1,4 @@
|
|
DRIVERS=="amdgpu", SUBSYSTEM=="drm", PROGRAM="@libexecdir@/check-discrete-amdgpu $env{DEVNAME}", TAG+="switcheroo-discrete-gpu"
|
|
DRIVERS=="nouveau", SUBSYSTEM=="drm", PROGRAM="@libexecdir@/check-discrete-nouveau $env{DEVNAME}", TAG+="switcheroo-discrete-gpu"
|
|
-DRIVERS=="nvidia", TAG+="switcheroo-discrete-gpu"
|
|
+DRIVERS=="nvidia", SUBSYSTEM=="drm", TAG+="switcheroo-discrete-gpu"
|
|
+DRIVERS=="i915", SUBSYSTEM=="drm", DEVPATH!="/devices/pci0000:00/0000:00:02.0/drm/*", TAG+="switcheroo-discrete-gpu"
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 55db3aeaeb962952881f73e94432f750cfb64fc8 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Thu, 15 Feb 2024 16:24:00 +0100
|
|
Subject: [PATCH 09/13] main: use Discrete key in switcherooctl
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
src/switcherooctl.in | 3 ++-
|
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/src/switcherooctl.in b/src/switcherooctl.in
|
|
index 96c21cc..c0e3f07 100755
|
|
--- a/src/switcherooctl.in
|
|
+++ b/src/switcherooctl.in
|
|
@@ -77,6 +77,7 @@ def print_gpu(gpu, index):
|
|
print('Device:', index)
|
|
print(' Name: ', gpu['Name'])
|
|
print(' Default: ', "yes" if gpu['Default'] else "no")
|
|
+ print(' Discrete: ', "yes" if gpu['Discrete'] else "no")
|
|
print(' Environment:', env_to_str(gpu['Environment']))
|
|
|
|
def _list():
|
|
@@ -126,7 +127,7 @@ def get_discrete_gpu():
|
|
return None
|
|
|
|
try:
|
|
- gpu = next(gpu for gpu in gpus if not gpu['Default'])
|
|
+ gpu = next(gpu for gpu in gpus if gpu['Discrete'])
|
|
except StopIteration:
|
|
return None
|
|
else:
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From 4232c75fe41158bb5063d630d36b3ffd6a8a57ec Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Fri, 6 Sep 2024 22:31:56 +0200
|
|
Subject: [PATCH 10/13] main: use new GPU list on uevent the amount of GPUs may
|
|
still be the same but underlying attributes may have changed On the ASUS TUF
|
|
Dash F15 running Fedora 40 6.10.7-200.fc40.x86_64 the udev tags are not
|
|
applied at the time switcheroo-control starts but at a later uevent they are
|
|
correct. Memory gets allocated anyways to check if the GPU count has changed,
|
|
so this shouldn't affect memory usage.
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
src/switcheroo-control.c | 16 ++++++----------
|
|
1 file changed, 6 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/src/switcheroo-control.c b/src/switcheroo-control.c
|
|
index 0f6a548..01954c7 100644
|
|
--- a/src/switcheroo-control.c
|
|
+++ b/src/switcheroo-control.c
|
|
@@ -438,16 +438,12 @@ uevent_cb (GUdevClient *client,
|
|
|
|
cards = get_drm_cards (data);
|
|
num_gpus = cards->len;
|
|
- if (num_gpus != data->num_gpus) {
|
|
- g_debug ("GPUs added or removed (old: %d new: %d)",
|
|
- data->num_gpus, num_gpus);
|
|
- g_ptr_array_free (data->cards, TRUE);
|
|
- data->cards = cards;
|
|
- data->num_gpus = cards->len;
|
|
- send_dbus_event (data);
|
|
- } else {
|
|
- g_ptr_array_free (cards, TRUE);
|
|
- }
|
|
+ g_debug ("GPUs updated (old: %d new: %d)",
|
|
+ data->num_gpus, num_gpus);
|
|
+ g_ptr_array_free (data->cards, TRUE);
|
|
+ data->cards = cards;
|
|
+ data->num_gpus = cards->len;
|
|
+ send_dbus_event (data);
|
|
}
|
|
|
|
static void
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From ad09f908cc9e56cccfc946b285f2e7ddd014c587 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Mon, 28 Apr 2025 21:41:47 +0200
|
|
Subject: [PATCH 11/13] main: add xe discrete detection
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
data/30-discrete-gpu.rules.in | 1 +
|
|
meson.build | 1 +
|
|
meson_options.txt | 6 +++
|
|
src/discrete-detection/meson.build | 9 +++++
|
|
src/discrete-detection/xe.c | 63 ++++++++++++++++++++++++++++++
|
|
5 files changed, 80 insertions(+)
|
|
create mode 100644 src/discrete-detection/xe.c
|
|
|
|
diff --git a/data/30-discrete-gpu.rules.in b/data/30-discrete-gpu.rules.in
|
|
index f30f315..ab60bf2 100644
|
|
--- a/data/30-discrete-gpu.rules.in
|
|
+++ b/data/30-discrete-gpu.rules.in
|
|
@@ -2,3 +2,4 @@ DRIVERS=="amdgpu", SUBSYSTEM=="drm", PROGRAM="@libexecdir@/check-discrete-amdgpu
|
|
DRIVERS=="nouveau", SUBSYSTEM=="drm", PROGRAM="@libexecdir@/check-discrete-nouveau $env{DEVNAME}", TAG+="switcheroo-discrete-gpu"
|
|
DRIVERS=="nvidia", SUBSYSTEM=="drm", TAG+="switcheroo-discrete-gpu"
|
|
DRIVERS=="i915", SUBSYSTEM=="drm", DEVPATH!="/devices/pci0000:00/0000:00:02.0/drm/*", TAG+="switcheroo-discrete-gpu"
|
|
+DRIVERS=="xe", SUBSYSTEM=="drm", PROGRAM="@libexecdir@/check-discrete-xe $env{DEVNAME}", TAG+="switcheroo-discrete-gpu"
|
|
diff --git a/meson.build b/meson.build
|
|
index b3aaf0c..31dfa95 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -23,6 +23,7 @@ gudev = dependency('gudev-1.0', version: '>= 232')
|
|
libdrm = dependency('libdrm', version: '>= 2.4.97', required: get_option('libdrm'))
|
|
libdrm_nouveau = dependency('libdrm_nouveau', version: '>= 2.4.97', required: get_option('libdrm_nouveau'))
|
|
libdrm_amdgpu = dependency('libdrm_amdgpu', version: '>= 2.4.97', required: get_option('libdrm_amdgpu'))
|
|
+drm_xe = cc.has_header('drm/xe_drm.h', required: get_option('drm_xe'))
|
|
|
|
systemd_systemunitdir = get_option('systemdsystemunitdir')
|
|
if systemd_systemunitdir == ''
|
|
diff --git a/meson_options.txt b/meson_options.txt
|
|
index c77fea8..058dbdd 100644
|
|
--- a/meson_options.txt
|
|
+++ b/meson_options.txt
|
|
@@ -45,3 +45,9 @@ option('libdrm_amdgpu',
|
|
type: 'feature',
|
|
value: 'auto'
|
|
)
|
|
+
|
|
+option('drm_xe',
|
|
+ description: 'Whether the kernel provided xe drm header should be used to probe Intel GPUs',
|
|
+ type: 'feature',
|
|
+ value: 'auto'
|
|
+)
|
|
diff --git a/src/discrete-detection/meson.build b/src/discrete-detection/meson.build
|
|
index 353316f..7e0b324 100644
|
|
--- a/src/discrete-detection/meson.build
|
|
+++ b/src/discrete-detection/meson.build
|
|
@@ -17,3 +17,12 @@ if libdrm.found() and libdrm_nouveau.found()
|
|
install_dir: libexecdir,
|
|
)
|
|
endif
|
|
+
|
|
+if drm_xe
|
|
+ xe_discrete = executable('check-discrete-xe',
|
|
+ files('xe.c'),
|
|
+ dependencies: deps,
|
|
+ install: true,
|
|
+ install_dir: libexecdir,
|
|
+ )
|
|
+endif
|
|
diff --git a/src/discrete-detection/xe.c b/src/discrete-detection/xe.c
|
|
new file mode 100644
|
|
index 0000000..5ee6ede
|
|
--- /dev/null
|
|
+++ b/src/discrete-detection/xe.c
|
|
@@ -0,0 +1,63 @@
|
|
+#include <fcntl.h>
|
|
+#include <stdint.h>
|
|
+#include <locale.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <gio/gio.h>
|
|
+
|
|
+#include <drm/xe_drm.h>
|
|
+
|
|
+typedef int handle;
|
|
+G_DEFINE_AUTO_CLEANUP_FREE_FUNC(handle, close, -1)
|
|
+
|
|
+int main (int argc, char** argv)
|
|
+{
|
|
+ const char *devname;
|
|
+ g_auto(handle) fd = -1;
|
|
+ g_autofree struct drm_xe_query_config *config = NULL;
|
|
+ g_autoptr(GOptionContext) option_context = NULL;
|
|
+ g_autoptr(GError) error = NULL;
|
|
+
|
|
+ setlocale (LC_ALL, "");
|
|
+ option_context = g_option_context_new ("");
|
|
+
|
|
+ if (!g_option_context_parse (option_context, &argc, &argv, &error)) {
|
|
+ g_print ("Failed to parse arguments: %s\n", error->message);
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ if (argc < 2)
|
|
+ {
|
|
+ g_print ("%s\n", g_option_context_get_help (option_context, TRUE, NULL));
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ devname = argv[1];
|
|
+
|
|
+ fd = open (devname, O_RDWR);
|
|
+ if (fd < 0)
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ struct drm_xe_device_query query = {
|
|
+ .extensions = 0,
|
|
+ .query = DRM_XE_DEVICE_QUERY_CONFIG,
|
|
+ .size = 0,
|
|
+ .data = 0,
|
|
+ };
|
|
+
|
|
+ if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query))
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ config = malloc(query.size);
|
|
+ if (!config)
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ query.data = (uintptr_t)config;
|
|
+ if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query))
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+ // if the GPU has dedicated vram then its discrrete
|
|
+ if (config->info[DRM_XE_QUERY_CONFIG_FLAGS] & DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM)
|
|
+ return EXIT_SUCCESS;
|
|
+
|
|
+ return EXIT_FAILURE;
|
|
+
|
|
+}
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From cefec04bfc28a32bbec1e5a25999a768a6a7bf9c Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Mon, 28 Apr 2025 21:39:48 +0200
|
|
Subject: [PATCH 12/13] tests: fix switcherooctl output test
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
tests/integration-test.py | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/tests/integration-test.py b/tests/integration-test.py
|
|
index e3dd996..5b4b4bb 100755
|
|
--- a/tests/integration-test.py
|
|
+++ b/tests/integration-test.py
|
|
@@ -512,7 +512,7 @@ class Tests(dbusmock.DBusTestCase):
|
|
|
|
out = subprocess.run([tool_path], capture_output=True)
|
|
self.assertEqual(out.returncode, 0, "'switcherooctl' call failed")
|
|
- self.assertEqual(out.stdout, b'Device: 0\n Name: Intel\xc2\xae UHD Graphics 620 (Kabylake GT2)\n Default: yes\n Environment: DRI_PRIME=pci-0000_00_02_0\n\nDevice: 1\n Name: GM108M [GeForce 930MX]\n Default: no\n Environment: DRI_PRIME=pci-0000_01_00_0\n')
|
|
+ self.assertEqual(out.stdout, b'Device: 0\n Name: Intel\xc2\xae UHD Graphics 620 (Kabylake GT2)\n Default: yes\n Discrete: no\n Environment: DRI_PRIME=pci-0000_00_02_0\n\nDevice: 1\n Name: GM108M [GeForce 930MX]\n Default: no\n Discrete: no\n Environment: DRI_PRIME=pci-0000_01_00_0\n')
|
|
|
|
out = subprocess.run([tool_path, 'launch', '--gpu', '0', 'env'], capture_output=True)
|
|
self.assertEqual(out.returncode, 0, "'switcherooctl launch --gpu 0' failed")
|
|
--
|
|
2.49.0
|
|
|
|
|
|
From a446971f7aef77218625eb8627ec34e86e403737 Mon Sep 17 00:00:00 2001
|
|
From: Jan200101 <sentrycraft123@gmail.com>
|
|
Date: Mon, 28 Apr 2025 21:53:21 +0200
|
|
Subject: [PATCH 13/13] tests: add tests for xe discrete detection
|
|
|
|
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
|
|
---
|
|
tests/discrete-detection/drm_xe_mock.c | 47 ++++++++++++++++++++++++++
|
|
tests/discrete-detection/meson.build | 42 ++++++++++++++++++++++-
|
|
2 files changed, 88 insertions(+), 1 deletion(-)
|
|
create mode 100644 tests/discrete-detection/drm_xe_mock.c
|
|
|
|
diff --git a/tests/discrete-detection/drm_xe_mock.c b/tests/discrete-detection/drm_xe_mock.c
|
|
new file mode 100644
|
|
index 0000000..a9da460
|
|
--- /dev/null
|
|
+++ b/tests/discrete-detection/drm_xe_mock.c
|
|
@@ -0,0 +1,47 @@
|
|
+#include <string.h>
|
|
+#include <stdint.h>
|
|
+#include <stdio.h>
|
|
+#include <errno.h>
|
|
+
|
|
+#include <drm/xe_drm.h>
|
|
+enum {
|
|
+ OTHER_GPU,
|
|
+ INTEL_IGPU,
|
|
+ INTEL_GPU,
|
|
+};
|
|
+
|
|
+/* Mock open(2) so we can test multiple devices configurations */
|
|
+int open(const char *pathname, int flags)
|
|
+{
|
|
+ if (!strcmp(pathname, "OTHER_GPU"))
|
|
+ return OTHER_GPU;
|
|
+ if (!strcmp (pathname, "INTEL_IGPU"))
|
|
+ return INTEL_IGPU;
|
|
+ if (!strcmp (pathname, "INTEL_GPU"))
|
|
+ return INTEL_GPU;
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+/* open64 may be used for large file support */
|
|
+int open64(const char *pathname, int flags)
|
|
+{
|
|
+ return open (pathname, flags);
|
|
+}
|
|
+
|
|
+int ioctl(int fd, unsigned long op, struct drm_xe_device_query* query)
|
|
+{
|
|
+ if (op != DRM_IOCTL_XE_DEVICE_QUERY)
|
|
+ return EINVAL;
|
|
+ if (fd == OTHER_GPU)
|
|
+ return ENODEV;
|
|
+
|
|
+ if (query->size == 0) {
|
|
+ query->size = sizeof(struct drm_xe_query_config);
|
|
+ } else {
|
|
+ struct drm_xe_query_config *config = (struct drm_xe_query_config*)query->data;
|
|
+ config->info[DRM_XE_QUERY_CONFIG_FLAGS] = fd == INTEL_GPU ? DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM : 0;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
diff --git a/tests/discrete-detection/meson.build b/tests/discrete-detection/meson.build
|
|
index f01a014..998229f 100644
|
|
--- a/tests/discrete-detection/meson.build
|
|
+++ b/tests/discrete-detection/meson.build
|
|
@@ -77,4 +77,44 @@ if libdrm.found() and libdrm_nouveau.found()
|
|
env: environment({'LD_PRELOAD': nouveau_mock_lib.full_path()}),
|
|
should_fail: false
|
|
)
|
|
-endif
|
|
\ No newline at end of file
|
|
+endif
|
|
+
|
|
+if drm_xe
|
|
+ xe_mock_lib = shared_library(
|
|
+ 'drm_xe_mock',
|
|
+ files('drm_xe_mock.c')
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test xe detection with invalid device',
|
|
+ xe_discrete,
|
|
+ args: ['NO_GPU'],
|
|
+ env: environment({'LD_PRELOAD': xe_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test xe detection with non-Intel GPU',
|
|
+ xe_discrete,
|
|
+ args: ['OTHER_GPU'],
|
|
+ env: environment({'LD_PRELOAD': xe_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test xe detection with Intel Integrated GPU',
|
|
+ xe_discrete,
|
|
+ args: ['INTEL_IGPU'],
|
|
+ env: environment({'LD_PRELOAD': xe_mock_lib.full_path()}),
|
|
+ should_fail: true
|
|
+ )
|
|
+
|
|
+ test(
|
|
+ 'test xe detection with Intel Discrete GPU',
|
|
+ xe_discrete,
|
|
+ args: ['INTEL_GPU'],
|
|
+ env: environment({'LD_PRELOAD': xe_mock_lib.full_path()}),
|
|
+ should_fail: false
|
|
+ )
|
|
+
|
|
+endif
|
|
--
|
|
2.49.0
|
|
|