diff options
author | Ondřej Lysoněk <olysonek@redhat.com> | 2018-11-06 15:49:04 +0100 |
---|---|---|
committer | Ondřej Lysoněk <olysonek@redhat.com> | 2018-11-23 12:16:52 +0100 |
commit | d4cb932567407cc3cfb40fa11763a7459a278741 (patch) | |
tree | 4e1c30ea082d062e1deeda27cb326bc6ed4eb16b /lib/sysfs.c | |
parent | 567e6a3b366e319224f5e5c36b9b83bd13362407 (diff) | |
download | lm-sensors-git-d4cb932567407cc3cfb40fa11763a7459a278741.tar.gz |
libsensors: Consider all ancestor devices when determining bus type
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 <olysonek@redhat.com>
Diffstat (limited to 'lib/sysfs.c')
-rw-r--r-- | lib/sysfs.c | 56 |
1 files 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 */ |