1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2020 Oxide Computer Company 14 */ 15 16 /* 17 * Construct sensors based on the ksensor framework for PCI devices. The kernel 18 * will create devices such that they show up 19 * /dev/sensors/temperature/pci/<bus>.<func>/<sensors>. This iterates and adds a 20 * sensor for the device based on the total number that exist for all of them. 21 */ 22 23 #include <sys/types.h> 24 #include <dirent.h> 25 #include <string.h> 26 #include <errno.h> 27 #include <fm/topo_mod.h> 28 #include <fm/topo_hc.h> 29 #include <pcibus.h> 30 #include <topo_sensor.h> 31 32 int 33 pci_create_dev_sensors(topo_mod_t *mod, tnode_t *dev) 34 { 35 int ret; 36 DIR *d; 37 char path[PATH_MAX]; 38 topo_instance_t binst, dinst; 39 struct dirent *ent; 40 tnode_t *parent = topo_node_parent(dev); 41 42 binst = topo_node_instance(parent); 43 dinst = topo_node_instance(dev); 44 45 if (snprintf(path, sizeof (path), "/dev/sensors/temperature/pci/%x.%x", 46 binst, dinst) >= sizeof (path)) { 47 topo_mod_dprintf(mod, "failed to construct temp sensor " 48 "directory path, path too long"); 49 return (topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM)); 50 } 51 52 topo_mod_dprintf(mod, "searching for sensors in %s", path); 53 54 d = opendir(path); 55 if (d == NULL) { 56 if (errno == ENOENT) { 57 return (0); 58 } 59 60 topo_mod_dprintf(mod, "failed to open %s: %s", path, 61 strerror(errno)); 62 return (topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM)); 63 } 64 65 while ((ent = readdir(d)) != NULL) { 66 char spath[PATH_MAX]; 67 68 if (strcmp(ent->d_name, ".") == 0 || 69 strcmp(ent->d_name, "..") == 0) { 70 continue; 71 } 72 73 if (snprintf(spath, sizeof (spath), "%s/%s", path, 74 ent->d_name) >= sizeof (spath)) { 75 topo_mod_dprintf(mod, "failed to construct temp sensor " 76 "path for %s/%s, path too long", path, ent->d_name); 77 ret = topo_mod_seterrno(mod, EMOD_UKNOWN_ENUM); 78 goto out; 79 } 80 81 topo_mod_dprintf(mod, "attempting to create sensor at %s", 82 spath); 83 if ((ret = topo_sensor_create_temp_sensor(mod, dev, spath, 84 ent->d_name)) < 0) { 85 goto out; 86 } 87 88 } 89 ret = 0; 90 91 out: 92 (void) closedir(d); 93 94 return (ret); 95 } 96