1*51dce24bSJeff Kirsher // SPDX-License-Identifier: GPL-2.0 2*51dce24bSJeff Kirsher /* Copyright(c) 1999 - 2018 Intel Corporation. */ 33ca8bc6dSDon Skidmore 43ca8bc6dSDon Skidmore #include "ixgbe.h" 53ca8bc6dSDon Skidmore #include "ixgbe_common.h" 63ca8bc6dSDon Skidmore #include "ixgbe_type.h" 73ca8bc6dSDon Skidmore 83ca8bc6dSDon Skidmore #include <linux/module.h> 93ca8bc6dSDon Skidmore #include <linux/types.h> 103ca8bc6dSDon Skidmore #include <linux/sysfs.h> 113ca8bc6dSDon Skidmore #include <linux/kobject.h> 123ca8bc6dSDon Skidmore #include <linux/device.h> 133ca8bc6dSDon Skidmore #include <linux/netdevice.h> 143ca8bc6dSDon Skidmore #include <linux/hwmon.h> 153ca8bc6dSDon Skidmore 163ca8bc6dSDon Skidmore /* hwmon callback functions */ 173ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_location(struct device *dev, 183ca8bc6dSDon Skidmore struct device_attribute *attr, 193ca8bc6dSDon Skidmore char *buf) 203ca8bc6dSDon Skidmore { 213ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 223ca8bc6dSDon Skidmore dev_attr); 233ca8bc6dSDon Skidmore return sprintf(buf, "loc%u\n", 243ca8bc6dSDon Skidmore ixgbe_attr->sensor->location); 253ca8bc6dSDon Skidmore } 263ca8bc6dSDon Skidmore 273ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_temp(struct device *dev, 283ca8bc6dSDon Skidmore struct device_attribute *attr, 293ca8bc6dSDon Skidmore char *buf) 303ca8bc6dSDon Skidmore { 313ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 323ca8bc6dSDon Skidmore dev_attr); 333ca8bc6dSDon Skidmore unsigned int value; 343ca8bc6dSDon Skidmore 353ca8bc6dSDon Skidmore /* reset the temp field */ 363ca8bc6dSDon Skidmore ixgbe_attr->hw->mac.ops.get_thermal_sensor_data(ixgbe_attr->hw); 373ca8bc6dSDon Skidmore 383ca8bc6dSDon Skidmore value = ixgbe_attr->sensor->temp; 393ca8bc6dSDon Skidmore 403ca8bc6dSDon Skidmore /* display millidegree */ 413ca8bc6dSDon Skidmore value *= 1000; 423ca8bc6dSDon Skidmore 433ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 443ca8bc6dSDon Skidmore } 453ca8bc6dSDon Skidmore 463ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_cautionthresh(struct device *dev, 473ca8bc6dSDon Skidmore struct device_attribute *attr, 483ca8bc6dSDon Skidmore char *buf) 493ca8bc6dSDon Skidmore { 503ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 513ca8bc6dSDon Skidmore dev_attr); 523ca8bc6dSDon Skidmore unsigned int value = ixgbe_attr->sensor->caution_thresh; 533ca8bc6dSDon Skidmore 543ca8bc6dSDon Skidmore /* display millidegree */ 553ca8bc6dSDon Skidmore value *= 1000; 563ca8bc6dSDon Skidmore 573ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 583ca8bc6dSDon Skidmore } 593ca8bc6dSDon Skidmore 603ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev, 613ca8bc6dSDon Skidmore struct device_attribute *attr, 623ca8bc6dSDon Skidmore char *buf) 633ca8bc6dSDon Skidmore { 643ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 653ca8bc6dSDon Skidmore dev_attr); 663ca8bc6dSDon Skidmore unsigned int value = ixgbe_attr->sensor->max_op_thresh; 673ca8bc6dSDon Skidmore 683ca8bc6dSDon Skidmore /* display millidegree */ 693ca8bc6dSDon Skidmore value *= 1000; 703ca8bc6dSDon Skidmore 713ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 723ca8bc6dSDon Skidmore } 733ca8bc6dSDon Skidmore 7449ce9c2cSBen Hutchings /** 753ca8bc6dSDon Skidmore * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file. 763ca8bc6dSDon Skidmore * @adapter: pointer to the adapter structure 773ca8bc6dSDon Skidmore * @offset: offset in the eeprom sensor data table 783ca8bc6dSDon Skidmore * @type: type of sensor data to display 793ca8bc6dSDon Skidmore * 803ca8bc6dSDon Skidmore * For each file we want in hwmon's sysfs interface we need a device_attribute 813ca8bc6dSDon Skidmore * This is included in our hwmon_attr struct that contains the references to 823ca8bc6dSDon Skidmore * the data structures we need to get the data to display. 833ca8bc6dSDon Skidmore */ 843ca8bc6dSDon Skidmore static int ixgbe_add_hwmon_attr(struct ixgbe_adapter *adapter, 853ca8bc6dSDon Skidmore unsigned int offset, int type) { 863ca8bc6dSDon Skidmore int rc; 873ca8bc6dSDon Skidmore unsigned int n_attr; 883ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr; 893ca8bc6dSDon Skidmore 9003b77d81SGuenter Roeck n_attr = adapter->ixgbe_hwmon_buff->n_hwmon; 9103b77d81SGuenter Roeck ixgbe_attr = &adapter->ixgbe_hwmon_buff->hwmon_list[n_attr]; 923ca8bc6dSDon Skidmore 933ca8bc6dSDon Skidmore switch (type) { 943ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_LOC: 953ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_location; 963ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 9722dd81c5SGuenter Roeck "temp%u_label", offset + 1); 983ca8bc6dSDon Skidmore break; 993ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_TEMP: 1003ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_temp; 1013ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 10222dd81c5SGuenter Roeck "temp%u_input", offset + 1); 1033ca8bc6dSDon Skidmore break; 1043ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_CAUTION: 1053ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_cautionthresh; 1063ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 10722dd81c5SGuenter Roeck "temp%u_max", offset + 1); 1083ca8bc6dSDon Skidmore break; 1093ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_MAX: 1103ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_maxopthresh; 1113ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 11222dd81c5SGuenter Roeck "temp%u_crit", offset + 1); 1133ca8bc6dSDon Skidmore break; 1143ca8bc6dSDon Skidmore default: 1153ca8bc6dSDon Skidmore rc = -EPERM; 1163ca8bc6dSDon Skidmore return rc; 1173ca8bc6dSDon Skidmore } 1183ca8bc6dSDon Skidmore 1193ca8bc6dSDon Skidmore /* These always the same regardless of type */ 1203ca8bc6dSDon Skidmore ixgbe_attr->sensor = 1213ca8bc6dSDon Skidmore &adapter->hw.mac.thermal_sensor_data.sensor[offset]; 1223ca8bc6dSDon Skidmore ixgbe_attr->hw = &adapter->hw; 1233ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.store = NULL; 124d3757ba4SJoe Perches ixgbe_attr->dev_attr.attr.mode = 0444; 1253ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.attr.name = ixgbe_attr->name; 12603b77d81SGuenter Roeck sysfs_attr_init(&ixgbe_attr->dev_attr.attr); 1273ca8bc6dSDon Skidmore 12803b77d81SGuenter Roeck adapter->ixgbe_hwmon_buff->attrs[n_attr] = &ixgbe_attr->dev_attr.attr; 1293ca8bc6dSDon Skidmore 13003b77d81SGuenter Roeck ++adapter->ixgbe_hwmon_buff->n_hwmon; 1313ca8bc6dSDon Skidmore 13203b77d81SGuenter Roeck return 0; 1333ca8bc6dSDon Skidmore } 1343ca8bc6dSDon Skidmore 1353ca8bc6dSDon Skidmore static void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter) 1363ca8bc6dSDon Skidmore { 1373ca8bc6dSDon Skidmore } 1383ca8bc6dSDon Skidmore 1393ca8bc6dSDon Skidmore /* called from ixgbe_main.c */ 1403ca8bc6dSDon Skidmore void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter) 1413ca8bc6dSDon Skidmore { 1423ca8bc6dSDon Skidmore ixgbe_sysfs_del_adapter(adapter); 1433ca8bc6dSDon Skidmore } 1443ca8bc6dSDon Skidmore 1453ca8bc6dSDon Skidmore /* called from ixgbe_main.c */ 1463ca8bc6dSDon Skidmore int ixgbe_sysfs_init(struct ixgbe_adapter *adapter) 1473ca8bc6dSDon Skidmore { 14803b77d81SGuenter Roeck struct hwmon_buff *ixgbe_hwmon; 14903b77d81SGuenter Roeck struct device *hwmon_dev; 1503ca8bc6dSDon Skidmore unsigned int i; 1513ca8bc6dSDon Skidmore int rc = 0; 1523ca8bc6dSDon Skidmore 1533ca8bc6dSDon Skidmore /* If this method isn't defined we don't support thermals */ 1543ca8bc6dSDon Skidmore if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) { 1551210982bSDon Skidmore goto exit; 1563ca8bc6dSDon Skidmore } 1573ca8bc6dSDon Skidmore 1583ca8bc6dSDon Skidmore /* Don't create thermal hwmon interface if no sensors present */ 1591210982bSDon Skidmore if (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)) 1601210982bSDon Skidmore goto exit; 1613ca8bc6dSDon Skidmore 16203b77d81SGuenter Roeck ixgbe_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*ixgbe_hwmon), 1633ca8bc6dSDon Skidmore GFP_KERNEL); 16403b77d81SGuenter Roeck if (ixgbe_hwmon == NULL) { 1653ca8bc6dSDon Skidmore rc = -ENOMEM; 16603b77d81SGuenter Roeck goto exit; 1673ca8bc6dSDon Skidmore } 16803b77d81SGuenter Roeck adapter->ixgbe_hwmon_buff = ixgbe_hwmon; 1693ca8bc6dSDon Skidmore 1703ca8bc6dSDon Skidmore for (i = 0; i < IXGBE_MAX_SENSORS; i++) { 1713ca8bc6dSDon Skidmore /* 1723ca8bc6dSDon Skidmore * Only create hwmon sysfs entries for sensors that have 1733ca8bc6dSDon Skidmore * meaningful data for. 1743ca8bc6dSDon Skidmore */ 1753ca8bc6dSDon Skidmore if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0) 1763ca8bc6dSDon Skidmore continue; 1773ca8bc6dSDon Skidmore 1783ca8bc6dSDon Skidmore /* Bail if any hwmon attr struct fails to initialize */ 1793ca8bc6dSDon Skidmore rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_CAUTION); 1803ca8bc6dSDon Skidmore if (rc) 18103b77d81SGuenter Roeck goto exit; 18203b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_LOC); 18303b77d81SGuenter Roeck if (rc) 18403b77d81SGuenter Roeck goto exit; 18503b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_TEMP); 18603b77d81SGuenter Roeck if (rc) 18703b77d81SGuenter Roeck goto exit; 18803b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_MAX); 18903b77d81SGuenter Roeck if (rc) 19003b77d81SGuenter Roeck goto exit; 1913ca8bc6dSDon Skidmore } 1923ca8bc6dSDon Skidmore 19303b77d81SGuenter Roeck ixgbe_hwmon->groups[0] = &ixgbe_hwmon->group; 19403b77d81SGuenter Roeck ixgbe_hwmon->group.attrs = ixgbe_hwmon->attrs; 1953ca8bc6dSDon Skidmore 19603b77d81SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev, 19703b77d81SGuenter Roeck "ixgbe", 19803b77d81SGuenter Roeck ixgbe_hwmon, 19903b77d81SGuenter Roeck ixgbe_hwmon->groups); 20003b77d81SGuenter Roeck if (IS_ERR(hwmon_dev)) 20103b77d81SGuenter Roeck rc = PTR_ERR(hwmon_dev); 2023ca8bc6dSDon Skidmore exit: 2033ca8bc6dSDon Skidmore return rc; 2043ca8bc6dSDon Skidmore } 2053ca8bc6dSDon Skidmore 206