From d4cb932567407cc3cfb40fa11763a7459a278741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= Date: Tue, 6 Nov 2018 15:49:04 +0100 Subject: [PATCH] libsensors: Consider all ancestor devices when determining bus type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Go through all ancestor devices of a hwmon device until we find a device that resides on a bus that we recognize. This change is meant to address hwmon devices that don't reside directly on a bus, but have another device in the middle of the hiearchy. For example: ACPI device -> thermal device -> hwmon device These kind of hwmon devices started appearing in the 4.19 kernel due to commit f6b6b52ef7a54160c0. It was not reported as a kernel regression and fixed in the kernel, because according to Documentation/admin-guide/sysfs-rules.rst, the change was OK to make (it says "Position of devices along device chain can change"). Fixes #133 Signed-off-by: Ondřej Lysoněk --- lib/sysfs.c | 56 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/lib/sysfs.c b/lib/sysfs.c index c05e0052..1691b9f5 100644 --- a/lib/sysfs.c +++ b/lib/sysfs.c @@ -707,28 +707,50 @@ static int find_bus_type(const char *dev_path, char linkpath[NAME_MAX]; char subsys_path[NAME_MAX], *subsys; int sub_len; + char *my_dev_path = NULL; + int ret = 0; + + my_dev_path = strdup(dev_path); + if (my_dev_path == NULL) + sensors_fatal_error(__func__, "Out of memory"); /* Find bus type */ - snprintf(linkpath, NAME_MAX, "%s/subsystem", dev_path); - sub_len = readlink(linkpath, subsys_path, NAME_MAX - 1); - if (sub_len < 0 && errno == ENOENT) { - /* Fallback to "bus" link for kernels <= 2.6.17 */ - snprintf(linkpath, NAME_MAX, "%s/bus", dev_path); + while (!ret && my_dev_path != NULL) { + snprintf(linkpath, NAME_MAX, "%s/subsystem", my_dev_path); sub_len = readlink(linkpath, subsys_path, NAME_MAX - 1); - } - if (sub_len < 0) { - /* Older kernels (<= 2.6.11) have neither the subsystem - symlink nor the bus symlink */ - if (errno == ENOENT) - subsys = NULL; - else - return -SENSORS_ERR_KERNEL; - } else { - subsys_path[sub_len] = '\0'; - subsys = strrchr(subsys_path, '/') + 1; + if (sub_len < 0 && errno == ENOENT) { + /* Fallback to "bus" link for kernels <= 2.6.17 */ + snprintf(linkpath, NAME_MAX, "%s/bus", my_dev_path); + sub_len = readlink(linkpath, subsys_path, NAME_MAX - 1); + } + if (sub_len < 0) { + /* Older kernels (<= 2.6.11) have neither the subsystem + symlink nor the bus symlink */ + if (errno == ENOENT) { + subsys = NULL; + } else { + ret = -SENSORS_ERR_KERNEL; + break; + } + } else { + subsys_path[sub_len] = '\0'; + subsys = strrchr(subsys_path, '/') + 1; + } + ret = classify_device(dev_name, subsys, entry); + if (!ret) { + snprintf(linkpath, NAME_MAX, "%s/device", my_dev_path); + free(my_dev_path); + my_dev_path = realpath(linkpath, NULL); + if (my_dev_path != NULL) + dev_name = strrchr(my_dev_path, '/') + 1; + else if (errno == ENOMEM) + sensors_fatal_error(__func__, "Out of memory"); + } } - return classify_device(dev_name, subsys, entry); + if (my_dev_path != NULL) + free(my_dev_path); + return ret; } /* returns: number of devices added (0 or 1) if successful, <0 otherwise */