From 5d1f6f300d448f41a58f0a15fdbda010368ea30b Mon Sep 17 00:00:00 2001 From: Kyle Gospodnetich Date: Thu, 2 Jan 2025 20:33:35 -0800 Subject: [PATCH] [frawhide] Add: Patched switcherooctl-control with Discrete GPU detection (#2841) --- ...pdate-GPUs-comment-for-dbus-property.patch | 27 ++ .../0002-main-add-Discrete-key.patch | 379 ++++++++++++++++++ ...x-integration-tests-without-UMockdev.patch | 27 ++ ...for-discrete-detection-with-mock-lib.patch | 278 +++++++++++++ ...05-main-remove-leftover-and-fix-typo.patch | 39 ++ ...screte-dependencies-out-of-main-deps.patch | 48 +++ ...-for-discrete-command-line-arguments.patch | 137 +++++++ .../0008-main-add-udev-rule-for-i915.patch | 25 ++ ...in-use-Discrete-key-in-switcherooctl.patch | 34 ++ ...0010-main-use-new-GPU-list-on-uevent.patch | 45 +++ anda/apps/switcheroo-control/anda.hcl | 8 + .../switcheroo-control.spec | 194 +++++++++ 12 files changed, 1241 insertions(+) create mode 100644 anda/apps/switcheroo-control/0001-main-update-GPUs-comment-for-dbus-property.patch create mode 100644 anda/apps/switcheroo-control/0002-main-add-Discrete-key.patch create mode 100644 anda/apps/switcheroo-control/0003-tests-fix-integration-tests-without-UMockdev.patch create mode 100644 anda/apps/switcheroo-control/0004-tests-add-tests-for-discrete-detection-with-mock-lib.patch create mode 100644 anda/apps/switcheroo-control/0005-main-remove-leftover-and-fix-typo.patch create mode 100644 anda/apps/switcheroo-control/0006-main-move-discrete-dependencies-out-of-main-deps.patch create mode 100644 anda/apps/switcheroo-control/0007-main-use-glib-for-discrete-command-line-arguments.patch create mode 100644 anda/apps/switcheroo-control/0008-main-add-udev-rule-for-i915.patch create mode 100644 anda/apps/switcheroo-control/0009-main-use-Discrete-key-in-switcherooctl.patch create mode 100644 anda/apps/switcheroo-control/0010-main-use-new-GPU-list-on-uevent.patch create mode 100644 anda/apps/switcheroo-control/anda.hcl create mode 100644 anda/apps/switcheroo-control/switcheroo-control.spec diff --git a/anda/apps/switcheroo-control/0001-main-update-GPUs-comment-for-dbus-property.patch b/anda/apps/switcheroo-control/0001-main-update-GPUs-comment-for-dbus-property.patch new file mode 100644 index 0000000000..825ca07b19 --- /dev/null +++ b/anda/apps/switcheroo-control/0001-main-update-GPUs-comment-for-dbus-property.patch @@ -0,0 +1,27 @@ +From 44046bfbcb30a19c45416113a2a82a4d17a1a998 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Mon, 14 Aug 2023 14:06:45 +0200 +Subject: [PATCH 01/10] main: update GPUs comment for dbus property + +Signed-off-by: Jan200101 +--- + 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. + --> + + +-- +2.46.0 + diff --git a/anda/apps/switcheroo-control/0002-main-add-Discrete-key.patch b/anda/apps/switcheroo-control/0002-main-add-Discrete-key.patch new file mode 100644 index 0000000000..b67ca67fae --- /dev/null +++ b/anda/apps/switcheroo-control/0002-main-add-Discrete-key.patch @@ -0,0 +1,379 @@ +From 4f31415cb61a50c2bcba1510a7511518417d0970 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Mon, 11 Sep 2023 15:21:46 +0200 +Subject: [PATCH 02/10] main: add Discrete key + +Signed-off-by: Jan200101 +--- + .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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++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.46.0 + diff --git a/anda/apps/switcheroo-control/0003-tests-fix-integration-tests-without-UMockdev.patch b/anda/apps/switcheroo-control/0003-tests-fix-integration-tests-without-UMockdev.patch new file mode 100644 index 0000000000..e8ee844d53 --- /dev/null +++ b/anda/apps/switcheroo-control/0003-tests-fix-integration-tests-without-UMockdev.patch @@ -0,0 +1,27 @@ +From 1b115ed72e03ff1169cbfddd79ef10890baca133 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Tue, 12 Sep 2023 15:53:40 +0200 +Subject: [PATCH 03/10] tests: fix integration tests without UMockdev + `gi.require_version` throws ValueError if the dependency cannot be found + +Signed-off-by: Jan200101 +--- + 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.46.0 + diff --git a/anda/apps/switcheroo-control/0004-tests-add-tests-for-discrete-detection-with-mock-lib.patch b/anda/apps/switcheroo-control/0004-tests-add-tests-for-discrete-detection-with-mock-lib.patch new file mode 100644 index 0000000000..24915eba46 --- /dev/null +++ b/anda/apps/switcheroo-control/0004-tests-add-tests-for-discrete-detection-with-mock-lib.patch @@ -0,0 +1,278 @@ +From d933e96bdb15679ae7653f929461982aa66973ba Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Tue, 12 Sep 2023 15:58:16 +0200 +Subject: [PATCH 04/10] 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 +--- + 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 ++#include ++#include ++ ++#include ++ ++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 ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++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.46.0 + diff --git a/anda/apps/switcheroo-control/0005-main-remove-leftover-and-fix-typo.patch b/anda/apps/switcheroo-control/0005-main-remove-leftover-and-fix-typo.patch new file mode 100644 index 0000000000..b10984fc67 --- /dev/null +++ b/anda/apps/switcheroo-control/0005-main-remove-leftover-and-fix-typo.patch @@ -0,0 +1,39 @@ +From c102b643945dc076d881497dd2ca5865938f7053 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Tue, 12 Sep 2023 15:57:47 +0200 +Subject: [PATCH 05/10] main: remove leftover and fix typo + +Signed-off-by: Jan200101 +--- + 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.46.0 + diff --git a/anda/apps/switcheroo-control/0006-main-move-discrete-dependencies-out-of-main-deps.patch b/anda/apps/switcheroo-control/0006-main-move-discrete-dependencies-out-of-main-deps.patch new file mode 100644 index 0000000000..18a0e42158 --- /dev/null +++ b/anda/apps/switcheroo-control/0006-main-move-discrete-dependencies-out-of-main-deps.patch @@ -0,0 +1,48 @@ +From f764db4eb565c19ba14155791fbfced3fb5d34c8 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Tue, 12 Sep 2023 15:58:27 +0200 +Subject: [PATCH 06/10] main: move discrete dependencies out of main deps + +Signed-off-by: Jan200101 +--- + 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.46.0 + diff --git a/anda/apps/switcheroo-control/0007-main-use-glib-for-discrete-command-line-arguments.patch b/anda/apps/switcheroo-control/0007-main-use-glib-for-discrete-command-line-arguments.patch new file mode 100644 index 0000000000..524930709f --- /dev/null +++ b/anda/apps/switcheroo-control/0007-main-use-glib-for-discrete-command-line-arguments.patch @@ -0,0 +1,137 @@ +From d2ecc29469d5572fd171926c9d1dbb1b851c7b09 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Tue, 12 Sep 2023 17:12:00 +0200 +Subject: [PATCH 07/10] main: use glib for discrete command-line arguments + +Signed-off-by: Jan200101 +--- + 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 + #include + #include ++#include + #include + #include ++#include + + #include + #include +@@ -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 + #include + #include ++#include + #include + #include ++#include + + #include + #include +@@ -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.46.0 + diff --git a/anda/apps/switcheroo-control/0008-main-add-udev-rule-for-i915.patch b/anda/apps/switcheroo-control/0008-main-add-udev-rule-for-i915.patch new file mode 100644 index 0000000000..b7a684a1c6 --- /dev/null +++ b/anda/apps/switcheroo-control/0008-main-add-udev-rule-for-i915.patch @@ -0,0 +1,25 @@ +From 462b09f02de37dfd2965d23cc7c4137bcf45a4ae Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Wed, 14 Feb 2024 20:25:42 +0100 +Subject: [PATCH 08/10] 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 +--- + 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.46.0 + diff --git a/anda/apps/switcheroo-control/0009-main-use-Discrete-key-in-switcherooctl.patch b/anda/apps/switcheroo-control/0009-main-use-Discrete-key-in-switcherooctl.patch new file mode 100644 index 0000000000..abb8fdf525 --- /dev/null +++ b/anda/apps/switcheroo-control/0009-main-use-Discrete-key-in-switcherooctl.patch @@ -0,0 +1,34 @@ +From 55db3aeaeb962952881f73e94432f750cfb64fc8 Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Thu, 15 Feb 2024 16:24:00 +0100 +Subject: [PATCH 09/10] main: use Discrete key in switcherooctl + +Signed-off-by: Jan200101 +--- + 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.46.0 + diff --git a/anda/apps/switcheroo-control/0010-main-use-new-GPU-list-on-uevent.patch b/anda/apps/switcheroo-control/0010-main-use-new-GPU-list-on-uevent.patch new file mode 100644 index 0000000000..9f55d398e7 --- /dev/null +++ b/anda/apps/switcheroo-control/0010-main-use-new-GPU-list-on-uevent.patch @@ -0,0 +1,45 @@ +From 4232c75fe41158bb5063d630d36b3ffd6a8a57ec Mon Sep 17 00:00:00 2001 +From: Jan200101 +Date: Fri, 6 Sep 2024 22:31:56 +0200 +Subject: [PATCH 10/10] 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 +--- + 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.46.0 + diff --git a/anda/apps/switcheroo-control/anda.hcl b/anda/apps/switcheroo-control/anda.hcl new file mode 100644 index 0000000000..66361551ee --- /dev/null +++ b/anda/apps/switcheroo-control/anda.hcl @@ -0,0 +1,8 @@ +project pkg { + rpm { + spec = "switcheroo-control.spec" + } + labels { + extra = 1 + } +} diff --git a/anda/apps/switcheroo-control/switcheroo-control.spec b/anda/apps/switcheroo-control/switcheroo-control.spec new file mode 100644 index 0000000000..dde67c0bb2 --- /dev/null +++ b/anda/apps/switcheroo-control/switcheroo-control.spec @@ -0,0 +1,194 @@ +Name: switcheroo-control +Version: 2.6 +Release: 8%{?dist} +Summary: D-Bus service to check the availability of dual-GPU + +License: GPLv3 +URL: https://gitlab.freedesktop.org/hadess/switcheroo-control/ +# URL from https://gitlab.freedesktop.org/hadess/switcheroo-control/-/releases +Source0: https://gitlab.freedesktop.org/hadess/switcheroo-control/uploads/86ea54ac7ddb901b6bf6e915209151f8/switcheroo-control-2.6.tar.xz +Patch: 0001-main-update-GPUs-comment-for-dbus-property.patch +Patch: 0002-main-add-Discrete-key.patch +Patch: 0003-tests-fix-integration-tests-without-UMockdev.patch +Patch: 0004-tests-add-tests-for-discrete-detection-with-mock-lib.patch +Patch: 0005-main-remove-leftover-and-fix-typo.patch +Patch: 0006-main-move-discrete-dependencies-out-of-main-deps.patch +Patch: 0007-main-use-glib-for-discrete-command-line-arguments.patch +Patch: 0008-main-add-udev-rule-for-i915.patch +Patch: 0009-main-use-Discrete-key-in-switcherooctl.patch +Patch: 0010-main-use-new-GPU-list-on-uevent.patch + +BuildRequires: gcc +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: gtk-doc +BuildRequires: meson +BuildRequires: systemd +BuildRequires: libdrm-devel +BuildRequires: python3-dbusmock +BuildRequires: umockdev + +%{?systemd_requires} + +%description +D-Bus service to check the availability of dual-GPU. + +%package docs +Summary: Documentation for %{name} +BuildArch: noarch + +%description docs + +This package contains the documentation for %{name}. + +%prep +%autosetup -p1 + + +%build +%meson -Dgtk_doc=true +%meson_build + + +%install +%meson_install + +%post +if [ $1 -eq 2 ] && [ -x /usr/bin/systemctl ] ; then + /usr/bin/systemctl daemon-reload +fi +%systemd_post switcheroo-control.service +%udev_hwdb_update + +%preun +%systemd_preun switcheroo-control.service + +%postun +%systemd_postun_with_restart switcheroo-control.service +%udev_hwdb_update + +%files +%license COPYING +%doc NEWS README.md +%{_bindir}/switcherooctl +%{_datadir}/dbus-1/system.d/net.hadess.SwitcherooControl.conf +%{_unitdir}/switcheroo-control.service +%{_libexecdir}/switcheroo-control +%{_udevhwdbdir}/30-pci-intel-gpu.hwdb +%{_mandir}/man1/switcherooctl.1* +%{_libexecdir}/check-discrete-amdgpu +%{_libexecdir}/check-discrete-nouveau +%{_udevrulesdir}/30-discrete-gpu.rules + +%files docs +%dir %{_datadir}/gtk-doc/ +%dir %{_datadir}/gtk-doc/html/ +%{_datadir}/gtk-doc/html/%{name}/ + +%changelog +* Fri Sep 06 2024 Jan200101 - 2.6-8 +- Update discrete patch + +* Thu Feb 15 2024 Jan Drögehoff - 2.6-7 +- Update discrete patch + +* Wed Feb 14 2024 Jan Drögehoff - 2.6-6 +- Add discrete patch + +* Sat Jan 27 2024 Fedora Release Engineering - 2.6-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Sat Jul 22 2023 Fedora Release Engineering - 2.6-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Sat Jan 21 2023 Fedora Release Engineering - 2.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Sat Jul 23 2022 Fedora Release Engineering - 2.6-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Fri Jul 01 2022 Bastien Nocera - 2.6-1 ++ switcheroo-control-2.6-1 +- Update to 2.6 + +* Fri Apr 29 2022 Bastien Nocera - 2.5-1 ++ switcheroo-control-2.5-1 +- Update to 2.5 + +* Sat Jan 22 2022 Fedora Release Engineering - 2.4-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Fri Jul 23 2021 Fedora Release Engineering - 2.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 2.4-3 +- Rebuilt for updated systemd-rpm-macros + See https://pagure.io/fesco/issue/2583. + +* Wed Jan 27 2021 Fedora Release Engineering - 2.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Mon Jan 04 2021 Bastien Nocera - 2.4-1 ++ switcheroo-control-2.4-1 +- Update to 2.4 + +* Wed Jul 29 2020 Fedora Release Engineering - 2.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Mon Apr 27 2020 Bastien Nocera - 2.2-1 ++ switcheroo-control-2.2-1 +- Update to 2.2 + +* Fri Jan 31 2020 Fedora Release Engineering - 2.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Jan 02 2020 Bastien Nocera - 2.1-1 ++ switcheroo-control-2.1-1 +- Update to 2.1 +- Fix crasher on startup (#1786846) + +* Thu Nov 21 2019 Bastien Nocera - 2.0-2 ++ switcheroo-control-2.0-2 +- Fix post scripts not reloading service file + +* Tue Nov 05 2019 Bastien Nocera - 2.0-1 ++ switcheroo-control-2.0-1 +- Update to 2.0 + +* Sat Jul 27 2019 Fedora Release Engineering - 1.3.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Mon Jun 17 2019 Bastien Nocera - 1.3.1-1 ++ switcheroo-control-1.3.1-1 +- Fix Secure Boot work-around + +* Wed Jun 12 2019 Bastien Nocera - 1.3-1 ++ switcheroo-control-1.3-1 +- Update to 1.3 +- Fix operation with SecureBoot enabled + +* Sun Feb 03 2019 Fedora Release Engineering - 1.1-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Sat Jul 14 2018 Fedora Release Engineering - 1.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Feb 09 2018 Fedora Release Engineering - 1.1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Thu Aug 03 2017 Fedora Release Engineering - 1.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 1.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sat Feb 11 2017 Fedora Release Engineering - 1.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Fri Nov 04 2016 Bastien Nocera - 1.1-1 ++ switcheroo-control-1.1-1 +- Update to 1.1 +- Don't throw errors when the machine doesn't have dual-GPU (#1391212) + +* Fri Oct 21 2016 Kalev Lember - 1.0-1 +- Initial Fedora packaging