13ca8bc6dSDon Skidmore /******************************************************************************* 23ca8bc6dSDon Skidmore 33ca8bc6dSDon Skidmore Intel 10 Gigabit PCI Express Linux driver 4434c5e39SDon Skidmore Copyright(c) 1999 - 2013 Intel Corporation. 53ca8bc6dSDon Skidmore 63ca8bc6dSDon Skidmore This program is free software; you can redistribute it and/or modify it 73ca8bc6dSDon Skidmore under the terms and conditions of the GNU General Public License, 83ca8bc6dSDon Skidmore version 2, as published by the Free Software Foundation. 93ca8bc6dSDon Skidmore 103ca8bc6dSDon Skidmore This program is distributed in the hope it will be useful, but WITHOUT 113ca8bc6dSDon Skidmore ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 123ca8bc6dSDon Skidmore FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 133ca8bc6dSDon Skidmore more details. 143ca8bc6dSDon Skidmore 153ca8bc6dSDon Skidmore You should have received a copy of the GNU General Public License along with 163ca8bc6dSDon Skidmore this program; if not, write to the Free Software Foundation, Inc., 173ca8bc6dSDon Skidmore 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 183ca8bc6dSDon Skidmore 193ca8bc6dSDon Skidmore The full GNU General Public License is included in this distribution in 203ca8bc6dSDon Skidmore the file called "COPYING". 213ca8bc6dSDon Skidmore 223ca8bc6dSDon Skidmore Contact Information: 23b89aae71SJacob Keller Linux NICS <linux.nics@intel.com> 243ca8bc6dSDon Skidmore e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 253ca8bc6dSDon Skidmore Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 263ca8bc6dSDon Skidmore 273ca8bc6dSDon Skidmore *******************************************************************************/ 283ca8bc6dSDon Skidmore 293ca8bc6dSDon Skidmore #include "ixgbe.h" 303ca8bc6dSDon Skidmore #include "ixgbe_common.h" 313ca8bc6dSDon Skidmore #include "ixgbe_type.h" 323ca8bc6dSDon Skidmore 333ca8bc6dSDon Skidmore #include <linux/module.h> 343ca8bc6dSDon Skidmore #include <linux/types.h> 353ca8bc6dSDon Skidmore #include <linux/sysfs.h> 363ca8bc6dSDon Skidmore #include <linux/kobject.h> 373ca8bc6dSDon Skidmore #include <linux/device.h> 383ca8bc6dSDon Skidmore #include <linux/netdevice.h> 393ca8bc6dSDon Skidmore #include <linux/hwmon.h> 403ca8bc6dSDon Skidmore 413ca8bc6dSDon Skidmore /* hwmon callback functions */ 423ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_location(struct device *dev, 433ca8bc6dSDon Skidmore struct device_attribute *attr, 443ca8bc6dSDon Skidmore char *buf) 453ca8bc6dSDon Skidmore { 463ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 473ca8bc6dSDon Skidmore dev_attr); 483ca8bc6dSDon Skidmore return sprintf(buf, "loc%u\n", 493ca8bc6dSDon Skidmore ixgbe_attr->sensor->location); 503ca8bc6dSDon Skidmore } 513ca8bc6dSDon Skidmore 523ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_temp(struct device *dev, 533ca8bc6dSDon Skidmore struct device_attribute *attr, 543ca8bc6dSDon Skidmore char *buf) 553ca8bc6dSDon Skidmore { 563ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 573ca8bc6dSDon Skidmore dev_attr); 583ca8bc6dSDon Skidmore unsigned int value; 593ca8bc6dSDon Skidmore 603ca8bc6dSDon Skidmore /* reset the temp field */ 613ca8bc6dSDon Skidmore ixgbe_attr->hw->mac.ops.get_thermal_sensor_data(ixgbe_attr->hw); 623ca8bc6dSDon Skidmore 633ca8bc6dSDon Skidmore value = ixgbe_attr->sensor->temp; 643ca8bc6dSDon Skidmore 653ca8bc6dSDon Skidmore /* display millidegree */ 663ca8bc6dSDon Skidmore value *= 1000; 673ca8bc6dSDon Skidmore 683ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 693ca8bc6dSDon Skidmore } 703ca8bc6dSDon Skidmore 713ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_cautionthresh(struct device *dev, 723ca8bc6dSDon Skidmore struct device_attribute *attr, 733ca8bc6dSDon Skidmore char *buf) 743ca8bc6dSDon Skidmore { 753ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 763ca8bc6dSDon Skidmore dev_attr); 773ca8bc6dSDon Skidmore unsigned int value = ixgbe_attr->sensor->caution_thresh; 783ca8bc6dSDon Skidmore 793ca8bc6dSDon Skidmore /* display millidegree */ 803ca8bc6dSDon Skidmore value *= 1000; 813ca8bc6dSDon Skidmore 823ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 833ca8bc6dSDon Skidmore } 843ca8bc6dSDon Skidmore 853ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev, 863ca8bc6dSDon Skidmore struct device_attribute *attr, 873ca8bc6dSDon Skidmore char *buf) 883ca8bc6dSDon Skidmore { 893ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 903ca8bc6dSDon Skidmore dev_attr); 913ca8bc6dSDon Skidmore unsigned int value = ixgbe_attr->sensor->max_op_thresh; 923ca8bc6dSDon Skidmore 933ca8bc6dSDon Skidmore /* display millidegree */ 943ca8bc6dSDon Skidmore value *= 1000; 953ca8bc6dSDon Skidmore 963ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 973ca8bc6dSDon Skidmore } 983ca8bc6dSDon Skidmore 9949ce9c2cSBen Hutchings /** 1003ca8bc6dSDon Skidmore * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file. 1013ca8bc6dSDon Skidmore * @adapter: pointer to the adapter structure 1023ca8bc6dSDon Skidmore * @offset: offset in the eeprom sensor data table 1033ca8bc6dSDon Skidmore * @type: type of sensor data to display 1043ca8bc6dSDon Skidmore * 1053ca8bc6dSDon Skidmore * For each file we want in hwmon's sysfs interface we need a device_attribute 1063ca8bc6dSDon Skidmore * This is included in our hwmon_attr struct that contains the references to 1073ca8bc6dSDon Skidmore * the data structures we need to get the data to display. 1083ca8bc6dSDon Skidmore */ 1093ca8bc6dSDon Skidmore static int ixgbe_add_hwmon_attr(struct ixgbe_adapter *adapter, 1103ca8bc6dSDon Skidmore unsigned int offset, int type) { 1113ca8bc6dSDon Skidmore int rc; 1123ca8bc6dSDon Skidmore unsigned int n_attr; 1133ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr; 1143ca8bc6dSDon Skidmore 11503b77d81SGuenter Roeck n_attr = adapter->ixgbe_hwmon_buff->n_hwmon; 11603b77d81SGuenter Roeck ixgbe_attr = &adapter->ixgbe_hwmon_buff->hwmon_list[n_attr]; 1173ca8bc6dSDon Skidmore 1183ca8bc6dSDon Skidmore switch (type) { 1193ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_LOC: 1203ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_location; 1213ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 12222dd81c5SGuenter Roeck "temp%u_label", offset + 1); 1233ca8bc6dSDon Skidmore break; 1243ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_TEMP: 1253ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_temp; 1263ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 12722dd81c5SGuenter Roeck "temp%u_input", offset + 1); 1283ca8bc6dSDon Skidmore break; 1293ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_CAUTION: 1303ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_cautionthresh; 1313ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 13222dd81c5SGuenter Roeck "temp%u_max", offset + 1); 1333ca8bc6dSDon Skidmore break; 1343ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_MAX: 1353ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_maxopthresh; 1363ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 13722dd81c5SGuenter Roeck "temp%u_crit", offset + 1); 1383ca8bc6dSDon Skidmore break; 1393ca8bc6dSDon Skidmore default: 1403ca8bc6dSDon Skidmore rc = -EPERM; 1413ca8bc6dSDon Skidmore return rc; 1423ca8bc6dSDon Skidmore } 1433ca8bc6dSDon Skidmore 1443ca8bc6dSDon Skidmore /* These always the same regardless of type */ 1453ca8bc6dSDon Skidmore ixgbe_attr->sensor = 1463ca8bc6dSDon Skidmore &adapter->hw.mac.thermal_sensor_data.sensor[offset]; 1473ca8bc6dSDon Skidmore ixgbe_attr->hw = &adapter->hw; 1483ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.store = NULL; 149*d3757ba4SJoe Perches ixgbe_attr->dev_attr.attr.mode = 0444; 1503ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.attr.name = ixgbe_attr->name; 15103b77d81SGuenter Roeck sysfs_attr_init(&ixgbe_attr->dev_attr.attr); 1523ca8bc6dSDon Skidmore 15303b77d81SGuenter Roeck adapter->ixgbe_hwmon_buff->attrs[n_attr] = &ixgbe_attr->dev_attr.attr; 1543ca8bc6dSDon Skidmore 15503b77d81SGuenter Roeck ++adapter->ixgbe_hwmon_buff->n_hwmon; 1563ca8bc6dSDon Skidmore 15703b77d81SGuenter Roeck return 0; 1583ca8bc6dSDon Skidmore } 1593ca8bc6dSDon Skidmore 1603ca8bc6dSDon Skidmore static void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter) 1613ca8bc6dSDon Skidmore { 1623ca8bc6dSDon Skidmore } 1633ca8bc6dSDon Skidmore 1643ca8bc6dSDon Skidmore /* called from ixgbe_main.c */ 1653ca8bc6dSDon Skidmore void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter) 1663ca8bc6dSDon Skidmore { 1673ca8bc6dSDon Skidmore ixgbe_sysfs_del_adapter(adapter); 1683ca8bc6dSDon Skidmore } 1693ca8bc6dSDon Skidmore 1703ca8bc6dSDon Skidmore /* called from ixgbe_main.c */ 1713ca8bc6dSDon Skidmore int ixgbe_sysfs_init(struct ixgbe_adapter *adapter) 1723ca8bc6dSDon Skidmore { 17303b77d81SGuenter Roeck struct hwmon_buff *ixgbe_hwmon; 17403b77d81SGuenter Roeck struct device *hwmon_dev; 1753ca8bc6dSDon Skidmore unsigned int i; 1763ca8bc6dSDon Skidmore int rc = 0; 1773ca8bc6dSDon Skidmore 1783ca8bc6dSDon Skidmore /* If this method isn't defined we don't support thermals */ 1793ca8bc6dSDon Skidmore if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) { 1801210982bSDon Skidmore goto exit; 1813ca8bc6dSDon Skidmore } 1823ca8bc6dSDon Skidmore 1833ca8bc6dSDon Skidmore /* Don't create thermal hwmon interface if no sensors present */ 1841210982bSDon Skidmore if (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)) 1851210982bSDon Skidmore goto exit; 1863ca8bc6dSDon Skidmore 18703b77d81SGuenter Roeck ixgbe_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*ixgbe_hwmon), 1883ca8bc6dSDon Skidmore GFP_KERNEL); 18903b77d81SGuenter Roeck if (ixgbe_hwmon == NULL) { 1903ca8bc6dSDon Skidmore rc = -ENOMEM; 19103b77d81SGuenter Roeck goto exit; 1923ca8bc6dSDon Skidmore } 19303b77d81SGuenter Roeck adapter->ixgbe_hwmon_buff = ixgbe_hwmon; 1943ca8bc6dSDon Skidmore 1953ca8bc6dSDon Skidmore for (i = 0; i < IXGBE_MAX_SENSORS; i++) { 1963ca8bc6dSDon Skidmore /* 1973ca8bc6dSDon Skidmore * Only create hwmon sysfs entries for sensors that have 1983ca8bc6dSDon Skidmore * meaningful data for. 1993ca8bc6dSDon Skidmore */ 2003ca8bc6dSDon Skidmore if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0) 2013ca8bc6dSDon Skidmore continue; 2023ca8bc6dSDon Skidmore 2033ca8bc6dSDon Skidmore /* Bail if any hwmon attr struct fails to initialize */ 2043ca8bc6dSDon Skidmore rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_CAUTION); 2053ca8bc6dSDon Skidmore if (rc) 20603b77d81SGuenter Roeck goto exit; 20703b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_LOC); 20803b77d81SGuenter Roeck if (rc) 20903b77d81SGuenter Roeck goto exit; 21003b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_TEMP); 21103b77d81SGuenter Roeck if (rc) 21203b77d81SGuenter Roeck goto exit; 21303b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_MAX); 21403b77d81SGuenter Roeck if (rc) 21503b77d81SGuenter Roeck goto exit; 2163ca8bc6dSDon Skidmore } 2173ca8bc6dSDon Skidmore 21803b77d81SGuenter Roeck ixgbe_hwmon->groups[0] = &ixgbe_hwmon->group; 21903b77d81SGuenter Roeck ixgbe_hwmon->group.attrs = ixgbe_hwmon->attrs; 2203ca8bc6dSDon Skidmore 22103b77d81SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev, 22203b77d81SGuenter Roeck "ixgbe", 22303b77d81SGuenter Roeck ixgbe_hwmon, 22403b77d81SGuenter Roeck ixgbe_hwmon->groups); 22503b77d81SGuenter Roeck if (IS_ERR(hwmon_dev)) 22603b77d81SGuenter Roeck rc = PTR_ERR(hwmon_dev); 2273ca8bc6dSDon Skidmore exit: 2283ca8bc6dSDon Skidmore return rc; 2293ca8bc6dSDon Skidmore } 2303ca8bc6dSDon Skidmore 231