summaryrefslogtreecommitdiff
path: root/src/backlight
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-08-09 02:02:02 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-08-17 14:22:43 +0900
commite0504dd011189d97a1ea813aabfe1e696742bcf5 (patch)
tree1972d3f4d5eb6ca5f6ea3308858e551619cc05f7 /src/backlight
parentf8ff4b60763cb3afc619119b2ed280d3b1fa0aba (diff)
downloadsystemd-e0504dd011189d97a1ea813aabfe1e696742bcf5.tar.gz
backlight: fix issue on multiple graphics cards system
If a system has multiple graphics cards, then we cannot associate platform backlight devices to backlight devices under PCI bus. Previously, in such case, vaidate_device() for a raw backlight device might erroneously detect a platform device and return false. So, users could not save/load backlight level. This makes validate_device() give up to associate platform devices on non-PCI bus with raw backlight devices. That may cause unwanted backlight level save or restore by systemd-backlight@.service, but users can workaround that by masking specific instances of the service. Closes #24223.
Diffstat (limited to 'src/backlight')
-rw-r--r--src/backlight/backlight.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/src/backlight/backlight.c b/src/backlight/backlight.c
index b01b94b2b6..b6474d31a7 100644
--- a/src/backlight/backlight.c
+++ b/src/backlight/backlight.c
@@ -21,6 +21,8 @@
#include "terminal-util.h"
#include "util.h"
+#define PCI_CLASS_GRAPHICS_CARD 0x30000
+
static int help(void) {
_cleanup_free_ char *link = NULL;
int r;
@@ -44,6 +46,47 @@ static int help(void) {
return 0;
}
+static int has_multiple_graphics_cards(void) {
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ sd_device *dev;
+ bool found = false;
+ int r;
+
+ r = sd_device_enumerator_new(&e);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_add_match_subsystem(e, "pci", /* match = */ true);
+ if (r < 0)
+ return r;
+
+ /* class is an unsigned number, let's validate the value later. */
+ r = sd_device_enumerator_add_match_sysattr(e, "class", NULL, /* match = */ true);
+ if (r < 0)
+ return r;
+
+ FOREACH_DEVICE(e, dev) {
+ const char *s;
+ unsigned long c;
+
+ if (sd_device_get_sysattr_value(dev, "class", &s) < 0)
+ continue;
+
+ if (safe_atolu(s, &c) < 0)
+ continue;
+
+ if (c != PCI_CLASS_GRAPHICS_CARD)
+ continue;
+
+ if (found)
+ return true; /* This is the second device. */
+
+ found = true; /* Found the first device. */
+ }
+
+ return false;
+}
+
static int find_pci_or_platform_parent(sd_device *device, sd_device **ret) {
const char *subsystem, *sysname, *value;
sd_device *parent;
@@ -86,7 +129,7 @@ static int find_pci_or_platform_parent(sd_device *device, sd_device **ret) {
value, subsystem, sysname);
/* Graphics card */
- if (class == 0x30000) {
+ if (class == PCI_CLASS_GRAPHICS_CARD) {
*ret = parent;
return 0;
}
@@ -200,6 +243,23 @@ static int validate_device(sd_device *device) {
if (r < 0)
return log_debug_errno(r, "Failed to add sysattr match: %m");
+ if (streq(subsystem, "pci")) {
+ r = has_multiple_graphics_cards();
+ if (r < 0)
+ return log_debug_errno(r, "Failed to check if the system has multiple graphics cards: %m");
+ if (r > 0) {
+ /* If the system has multiple graphics cards, then we cannot associate platform
+ * devices on non-PCI bus (especially WMI bus) with PCI devices. Let's ignore all
+ * backlight devices that do not have the same parent PCI device. */
+ log_debug("Found multiple graphics cards on PCI bus. "
+ "Skipping to associate platform backlight devices on non-PCI bus.");
+
+ r = sd_device_enumerator_add_match_parent(enumerate, parent);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to add parent match: %m");
+ }
+ }
+
FOREACH_DEVICE(enumerate, other) {
const char *other_subsystem;
sd_device *other_parent;