summaryrefslogtreecommitdiff
path: root/lib/sysfs.c
diff options
context:
space:
mode:
authorOndřej Lysoněk <olysonek@redhat.com>2018-11-06 15:49:04 +0100
committerOndřej Lysoněk <olysonek@redhat.com>2018-11-23 12:16:52 +0100
commitd4cb932567407cc3cfb40fa11763a7459a278741 (patch)
tree4e1c30ea082d062e1deeda27cb326bc6ed4eb16b /lib/sysfs.c
parent567e6a3b366e319224f5e5c36b9b83bd13362407 (diff)
downloadlm-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.c56
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 */