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: 233ca8bc6dSDon Skidmore e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> 243ca8bc6dSDon Skidmore Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 253ca8bc6dSDon Skidmore 263ca8bc6dSDon Skidmore *******************************************************************************/ 273ca8bc6dSDon Skidmore 283ca8bc6dSDon Skidmore #include "ixgbe.h" 293ca8bc6dSDon Skidmore #include "ixgbe_common.h" 303ca8bc6dSDon Skidmore #include "ixgbe_type.h" 313ca8bc6dSDon Skidmore 323ca8bc6dSDon Skidmore #include <linux/module.h> 333ca8bc6dSDon Skidmore #include <linux/types.h> 343ca8bc6dSDon Skidmore #include <linux/sysfs.h> 353ca8bc6dSDon Skidmore #include <linux/kobject.h> 363ca8bc6dSDon Skidmore #include <linux/device.h> 373ca8bc6dSDon Skidmore #include <linux/netdevice.h> 383ca8bc6dSDon Skidmore #include <linux/hwmon.h> 393ca8bc6dSDon Skidmore 403ca8bc6dSDon Skidmore /* hwmon callback functions */ 413ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_location(struct device *dev, 423ca8bc6dSDon Skidmore struct device_attribute *attr, 433ca8bc6dSDon Skidmore char *buf) 443ca8bc6dSDon Skidmore { 453ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 463ca8bc6dSDon Skidmore dev_attr); 473ca8bc6dSDon Skidmore return sprintf(buf, "loc%u\n", 483ca8bc6dSDon Skidmore ixgbe_attr->sensor->location); 493ca8bc6dSDon Skidmore } 503ca8bc6dSDon Skidmore 513ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_temp(struct device *dev, 523ca8bc6dSDon Skidmore struct device_attribute *attr, 533ca8bc6dSDon Skidmore char *buf) 543ca8bc6dSDon Skidmore { 553ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 563ca8bc6dSDon Skidmore dev_attr); 573ca8bc6dSDon Skidmore unsigned int value; 583ca8bc6dSDon Skidmore 593ca8bc6dSDon Skidmore /* reset the temp field */ 603ca8bc6dSDon Skidmore ixgbe_attr->hw->mac.ops.get_thermal_sensor_data(ixgbe_attr->hw); 613ca8bc6dSDon Skidmore 623ca8bc6dSDon Skidmore value = ixgbe_attr->sensor->temp; 633ca8bc6dSDon Skidmore 643ca8bc6dSDon Skidmore /* display millidegree */ 653ca8bc6dSDon Skidmore value *= 1000; 663ca8bc6dSDon Skidmore 673ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 683ca8bc6dSDon Skidmore } 693ca8bc6dSDon Skidmore 703ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_cautionthresh(struct device *dev, 713ca8bc6dSDon Skidmore struct device_attribute *attr, 723ca8bc6dSDon Skidmore char *buf) 733ca8bc6dSDon Skidmore { 743ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 753ca8bc6dSDon Skidmore dev_attr); 763ca8bc6dSDon Skidmore unsigned int value = ixgbe_attr->sensor->caution_thresh; 773ca8bc6dSDon Skidmore 783ca8bc6dSDon Skidmore /* display millidegree */ 793ca8bc6dSDon Skidmore value *= 1000; 803ca8bc6dSDon Skidmore 813ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 823ca8bc6dSDon Skidmore } 833ca8bc6dSDon Skidmore 843ca8bc6dSDon Skidmore static ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev, 853ca8bc6dSDon Skidmore struct device_attribute *attr, 863ca8bc6dSDon Skidmore char *buf) 873ca8bc6dSDon Skidmore { 883ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 893ca8bc6dSDon Skidmore dev_attr); 903ca8bc6dSDon Skidmore unsigned int value = ixgbe_attr->sensor->max_op_thresh; 913ca8bc6dSDon Skidmore 923ca8bc6dSDon Skidmore /* display millidegree */ 933ca8bc6dSDon Skidmore value *= 1000; 943ca8bc6dSDon Skidmore 953ca8bc6dSDon Skidmore return sprintf(buf, "%u\n", value); 963ca8bc6dSDon Skidmore } 973ca8bc6dSDon Skidmore 9849ce9c2cSBen Hutchings /** 993ca8bc6dSDon Skidmore * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file. 1003ca8bc6dSDon Skidmore * @adapter: pointer to the adapter structure 1013ca8bc6dSDon Skidmore * @offset: offset in the eeprom sensor data table 1023ca8bc6dSDon Skidmore * @type: type of sensor data to display 1033ca8bc6dSDon Skidmore * 1043ca8bc6dSDon Skidmore * For each file we want in hwmon's sysfs interface we need a device_attribute 1053ca8bc6dSDon Skidmore * This is included in our hwmon_attr struct that contains the references to 1063ca8bc6dSDon Skidmore * the data structures we need to get the data to display. 1073ca8bc6dSDon Skidmore */ 1083ca8bc6dSDon Skidmore static int ixgbe_add_hwmon_attr(struct ixgbe_adapter *adapter, 1093ca8bc6dSDon Skidmore unsigned int offset, int type) { 1103ca8bc6dSDon Skidmore int rc; 1113ca8bc6dSDon Skidmore unsigned int n_attr; 1123ca8bc6dSDon Skidmore struct hwmon_attr *ixgbe_attr; 1133ca8bc6dSDon Skidmore 11403b77d81SGuenter Roeck n_attr = adapter->ixgbe_hwmon_buff->n_hwmon; 11503b77d81SGuenter Roeck ixgbe_attr = &adapter->ixgbe_hwmon_buff->hwmon_list[n_attr]; 1163ca8bc6dSDon Skidmore 1173ca8bc6dSDon Skidmore switch (type) { 1183ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_LOC: 1193ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_location; 1203ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 121*22dd81c5SGuenter Roeck "temp%u_label", offset + 1); 1223ca8bc6dSDon Skidmore break; 1233ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_TEMP: 1243ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_temp; 1253ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 126*22dd81c5SGuenter Roeck "temp%u_input", offset + 1); 1273ca8bc6dSDon Skidmore break; 1283ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_CAUTION: 1293ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_cautionthresh; 1303ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 131*22dd81c5SGuenter Roeck "temp%u_max", offset + 1); 1323ca8bc6dSDon Skidmore break; 1333ca8bc6dSDon Skidmore case IXGBE_HWMON_TYPE_MAX: 1343ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_maxopthresh; 1353ca8bc6dSDon Skidmore snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 136*22dd81c5SGuenter Roeck "temp%u_crit", offset + 1); 1373ca8bc6dSDon Skidmore break; 1383ca8bc6dSDon Skidmore default: 1393ca8bc6dSDon Skidmore rc = -EPERM; 1403ca8bc6dSDon Skidmore return rc; 1413ca8bc6dSDon Skidmore } 1423ca8bc6dSDon Skidmore 1433ca8bc6dSDon Skidmore /* These always the same regardless of type */ 1443ca8bc6dSDon Skidmore ixgbe_attr->sensor = 1453ca8bc6dSDon Skidmore &adapter->hw.mac.thermal_sensor_data.sensor[offset]; 1463ca8bc6dSDon Skidmore ixgbe_attr->hw = &adapter->hw; 1473ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.store = NULL; 1483ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.attr.mode = S_IRUGO; 1493ca8bc6dSDon Skidmore ixgbe_attr->dev_attr.attr.name = ixgbe_attr->name; 15003b77d81SGuenter Roeck sysfs_attr_init(&ixgbe_attr->dev_attr.attr); 1513ca8bc6dSDon Skidmore 15203b77d81SGuenter Roeck adapter->ixgbe_hwmon_buff->attrs[n_attr] = &ixgbe_attr->dev_attr.attr; 1533ca8bc6dSDon Skidmore 15403b77d81SGuenter Roeck ++adapter->ixgbe_hwmon_buff->n_hwmon; 1553ca8bc6dSDon Skidmore 15603b77d81SGuenter Roeck return 0; 1573ca8bc6dSDon Skidmore } 1583ca8bc6dSDon Skidmore 1593ca8bc6dSDon Skidmore static void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter) 1603ca8bc6dSDon Skidmore { 1613ca8bc6dSDon Skidmore } 1623ca8bc6dSDon Skidmore 1633ca8bc6dSDon Skidmore /* called from ixgbe_main.c */ 1643ca8bc6dSDon Skidmore void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter) 1653ca8bc6dSDon Skidmore { 1663ca8bc6dSDon Skidmore ixgbe_sysfs_del_adapter(adapter); 1673ca8bc6dSDon Skidmore } 1683ca8bc6dSDon Skidmore 1693ca8bc6dSDon Skidmore /* called from ixgbe_main.c */ 1703ca8bc6dSDon Skidmore int ixgbe_sysfs_init(struct ixgbe_adapter *adapter) 1713ca8bc6dSDon Skidmore { 17203b77d81SGuenter Roeck struct hwmon_buff *ixgbe_hwmon; 17303b77d81SGuenter Roeck struct device *hwmon_dev; 1743ca8bc6dSDon Skidmore unsigned int i; 1753ca8bc6dSDon Skidmore int rc = 0; 1763ca8bc6dSDon Skidmore 1773ca8bc6dSDon Skidmore /* If this method isn't defined we don't support thermals */ 1783ca8bc6dSDon Skidmore if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) { 1791210982bSDon Skidmore goto exit; 1803ca8bc6dSDon Skidmore } 1813ca8bc6dSDon Skidmore 1823ca8bc6dSDon Skidmore /* Don't create thermal hwmon interface if no sensors present */ 1831210982bSDon Skidmore if (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)) 1841210982bSDon Skidmore goto exit; 1853ca8bc6dSDon Skidmore 18603b77d81SGuenter Roeck ixgbe_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*ixgbe_hwmon), 1873ca8bc6dSDon Skidmore GFP_KERNEL); 18803b77d81SGuenter Roeck if (ixgbe_hwmon == NULL) { 1893ca8bc6dSDon Skidmore rc = -ENOMEM; 19003b77d81SGuenter Roeck goto exit; 1913ca8bc6dSDon Skidmore } 19203b77d81SGuenter Roeck adapter->ixgbe_hwmon_buff = ixgbe_hwmon; 1933ca8bc6dSDon Skidmore 1943ca8bc6dSDon Skidmore for (i = 0; i < IXGBE_MAX_SENSORS; i++) { 1953ca8bc6dSDon Skidmore /* 1963ca8bc6dSDon Skidmore * Only create hwmon sysfs entries for sensors that have 1973ca8bc6dSDon Skidmore * meaningful data for. 1983ca8bc6dSDon Skidmore */ 1993ca8bc6dSDon Skidmore if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0) 2003ca8bc6dSDon Skidmore continue; 2013ca8bc6dSDon Skidmore 2023ca8bc6dSDon Skidmore /* Bail if any hwmon attr struct fails to initialize */ 2033ca8bc6dSDon Skidmore rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_CAUTION); 2043ca8bc6dSDon Skidmore if (rc) 20503b77d81SGuenter Roeck goto exit; 20603b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_LOC); 20703b77d81SGuenter Roeck if (rc) 20803b77d81SGuenter Roeck goto exit; 20903b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_TEMP); 21003b77d81SGuenter Roeck if (rc) 21103b77d81SGuenter Roeck goto exit; 21203b77d81SGuenter Roeck rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_MAX); 21303b77d81SGuenter Roeck if (rc) 21403b77d81SGuenter Roeck goto exit; 2153ca8bc6dSDon Skidmore } 2163ca8bc6dSDon Skidmore 21703b77d81SGuenter Roeck ixgbe_hwmon->groups[0] = &ixgbe_hwmon->group; 21803b77d81SGuenter Roeck ixgbe_hwmon->group.attrs = ixgbe_hwmon->attrs; 2193ca8bc6dSDon Skidmore 22003b77d81SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev, 22103b77d81SGuenter Roeck "ixgbe", 22203b77d81SGuenter Roeck ixgbe_hwmon, 22303b77d81SGuenter Roeck ixgbe_hwmon->groups); 22403b77d81SGuenter Roeck if (IS_ERR(hwmon_dev)) 22503b77d81SGuenter Roeck rc = PTR_ERR(hwmon_dev); 2263ca8bc6dSDon Skidmore exit: 2273ca8bc6dSDon Skidmore return rc; 2283ca8bc6dSDon Skidmore } 2293ca8bc6dSDon Skidmore 230