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>
This commit is contained in:
Ondřej Lysoněk committed 2018-11-23 12:16:52 +01:00
1 parent 567e6a3b36
commit d4cb932567
1 file changed
+39 -17
+39 -17
View File
@@ -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 */