18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "ixgbe.h" 58c2ecf20Sopenharmony_ci#include "ixgbe_common.h" 68c2ecf20Sopenharmony_ci#include "ixgbe_type.h" 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/types.h> 108c2ecf20Sopenharmony_ci#include <linux/sysfs.h> 118c2ecf20Sopenharmony_ci#include <linux/kobject.h> 128c2ecf20Sopenharmony_ci#include <linux/device.h> 138c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 148c2ecf20Sopenharmony_ci#include <linux/hwmon.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* hwmon callback functions */ 178c2ecf20Sopenharmony_cistatic ssize_t ixgbe_hwmon_show_location(struct device *dev, 188c2ecf20Sopenharmony_ci struct device_attribute *attr, 198c2ecf20Sopenharmony_ci char *buf) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 228c2ecf20Sopenharmony_ci dev_attr); 238c2ecf20Sopenharmony_ci return sprintf(buf, "loc%u\n", 248c2ecf20Sopenharmony_ci ixgbe_attr->sensor->location); 258c2ecf20Sopenharmony_ci} 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic ssize_t ixgbe_hwmon_show_temp(struct device *dev, 288c2ecf20Sopenharmony_ci struct device_attribute *attr, 298c2ecf20Sopenharmony_ci char *buf) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 328c2ecf20Sopenharmony_ci dev_attr); 338c2ecf20Sopenharmony_ci unsigned int value; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* reset the temp field */ 368c2ecf20Sopenharmony_ci ixgbe_attr->hw->mac.ops.get_thermal_sensor_data(ixgbe_attr->hw); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci value = ixgbe_attr->sensor->temp; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* display millidegree */ 418c2ecf20Sopenharmony_ci value *= 1000; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", value); 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic ssize_t ixgbe_hwmon_show_cautionthresh(struct device *dev, 478c2ecf20Sopenharmony_ci struct device_attribute *attr, 488c2ecf20Sopenharmony_ci char *buf) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 518c2ecf20Sopenharmony_ci dev_attr); 528c2ecf20Sopenharmony_ci unsigned int value = ixgbe_attr->sensor->caution_thresh; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* display millidegree */ 558c2ecf20Sopenharmony_ci value *= 1000; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", value); 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev, 618c2ecf20Sopenharmony_ci struct device_attribute *attr, 628c2ecf20Sopenharmony_ci char *buf) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr, 658c2ecf20Sopenharmony_ci dev_attr); 668c2ecf20Sopenharmony_ci unsigned int value = ixgbe_attr->sensor->max_op_thresh; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci /* display millidegree */ 698c2ecf20Sopenharmony_ci value *= 1000; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", value); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/** 758c2ecf20Sopenharmony_ci * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file. 768c2ecf20Sopenharmony_ci * @adapter: pointer to the adapter structure 778c2ecf20Sopenharmony_ci * @offset: offset in the eeprom sensor data table 788c2ecf20Sopenharmony_ci * @type: type of sensor data to display 798c2ecf20Sopenharmony_ci * 808c2ecf20Sopenharmony_ci * For each file we want in hwmon's sysfs interface we need a device_attribute 818c2ecf20Sopenharmony_ci * This is included in our hwmon_attr struct that contains the references to 828c2ecf20Sopenharmony_ci * the data structures we need to get the data to display. 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_cistatic int ixgbe_add_hwmon_attr(struct ixgbe_adapter *adapter, 858c2ecf20Sopenharmony_ci unsigned int offset, int type) { 868c2ecf20Sopenharmony_ci int rc; 878c2ecf20Sopenharmony_ci unsigned int n_attr; 888c2ecf20Sopenharmony_ci struct hwmon_attr *ixgbe_attr; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci n_attr = adapter->ixgbe_hwmon_buff->n_hwmon; 918c2ecf20Sopenharmony_ci ixgbe_attr = &adapter->ixgbe_hwmon_buff->hwmon_list[n_attr]; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci switch (type) { 948c2ecf20Sopenharmony_ci case IXGBE_HWMON_TYPE_LOC: 958c2ecf20Sopenharmony_ci ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_location; 968c2ecf20Sopenharmony_ci snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 978c2ecf20Sopenharmony_ci "temp%u_label", offset + 1); 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci case IXGBE_HWMON_TYPE_TEMP: 1008c2ecf20Sopenharmony_ci ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_temp; 1018c2ecf20Sopenharmony_ci snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 1028c2ecf20Sopenharmony_ci "temp%u_input", offset + 1); 1038c2ecf20Sopenharmony_ci break; 1048c2ecf20Sopenharmony_ci case IXGBE_HWMON_TYPE_CAUTION: 1058c2ecf20Sopenharmony_ci ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_cautionthresh; 1068c2ecf20Sopenharmony_ci snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 1078c2ecf20Sopenharmony_ci "temp%u_max", offset + 1); 1088c2ecf20Sopenharmony_ci break; 1098c2ecf20Sopenharmony_ci case IXGBE_HWMON_TYPE_MAX: 1108c2ecf20Sopenharmony_ci ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_maxopthresh; 1118c2ecf20Sopenharmony_ci snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name), 1128c2ecf20Sopenharmony_ci "temp%u_crit", offset + 1); 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci default: 1158c2ecf20Sopenharmony_ci rc = -EPERM; 1168c2ecf20Sopenharmony_ci return rc; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* These always the same regardless of type */ 1208c2ecf20Sopenharmony_ci ixgbe_attr->sensor = 1218c2ecf20Sopenharmony_ci &adapter->hw.mac.thermal_sensor_data.sensor[offset]; 1228c2ecf20Sopenharmony_ci ixgbe_attr->hw = &adapter->hw; 1238c2ecf20Sopenharmony_ci ixgbe_attr->dev_attr.store = NULL; 1248c2ecf20Sopenharmony_ci ixgbe_attr->dev_attr.attr.mode = 0444; 1258c2ecf20Sopenharmony_ci ixgbe_attr->dev_attr.attr.name = ixgbe_attr->name; 1268c2ecf20Sopenharmony_ci sysfs_attr_init(&ixgbe_attr->dev_attr.attr); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci adapter->ixgbe_hwmon_buff->attrs[n_attr] = &ixgbe_attr->dev_attr.attr; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci ++adapter->ixgbe_hwmon_buff->n_hwmon; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci return 0; 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter) 1368c2ecf20Sopenharmony_ci{ 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/* called from ixgbe_main.c */ 1408c2ecf20Sopenharmony_civoid ixgbe_sysfs_exit(struct ixgbe_adapter *adapter) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci ixgbe_sysfs_del_adapter(adapter); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/* called from ixgbe_main.c */ 1468c2ecf20Sopenharmony_ciint ixgbe_sysfs_init(struct ixgbe_adapter *adapter) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci struct hwmon_buff *ixgbe_hwmon; 1498c2ecf20Sopenharmony_ci struct device *hwmon_dev; 1508c2ecf20Sopenharmony_ci unsigned int i; 1518c2ecf20Sopenharmony_ci int rc = 0; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci /* If this method isn't defined we don't support thermals */ 1548c2ecf20Sopenharmony_ci if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) { 1558c2ecf20Sopenharmony_ci goto exit; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Don't create thermal hwmon interface if no sensors present */ 1598c2ecf20Sopenharmony_ci if (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw)) 1608c2ecf20Sopenharmony_ci goto exit; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci ixgbe_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*ixgbe_hwmon), 1638c2ecf20Sopenharmony_ci GFP_KERNEL); 1648c2ecf20Sopenharmony_ci if (ixgbe_hwmon == NULL) { 1658c2ecf20Sopenharmony_ci rc = -ENOMEM; 1668c2ecf20Sopenharmony_ci goto exit; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci adapter->ixgbe_hwmon_buff = ixgbe_hwmon; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci for (i = 0; i < IXGBE_MAX_SENSORS; i++) { 1718c2ecf20Sopenharmony_ci /* 1728c2ecf20Sopenharmony_ci * Only create hwmon sysfs entries for sensors that have 1738c2ecf20Sopenharmony_ci * meaningful data for. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ci if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0) 1768c2ecf20Sopenharmony_ci continue; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* Bail if any hwmon attr struct fails to initialize */ 1798c2ecf20Sopenharmony_ci rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_CAUTION); 1808c2ecf20Sopenharmony_ci if (rc) 1818c2ecf20Sopenharmony_ci goto exit; 1828c2ecf20Sopenharmony_ci rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_LOC); 1838c2ecf20Sopenharmony_ci if (rc) 1848c2ecf20Sopenharmony_ci goto exit; 1858c2ecf20Sopenharmony_ci rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_TEMP); 1868c2ecf20Sopenharmony_ci if (rc) 1878c2ecf20Sopenharmony_ci goto exit; 1888c2ecf20Sopenharmony_ci rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_MAX); 1898c2ecf20Sopenharmony_ci if (rc) 1908c2ecf20Sopenharmony_ci goto exit; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci ixgbe_hwmon->groups[0] = &ixgbe_hwmon->group; 1948c2ecf20Sopenharmony_ci ixgbe_hwmon->group.attrs = ixgbe_hwmon->attrs; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev, 1978c2ecf20Sopenharmony_ci "ixgbe", 1988c2ecf20Sopenharmony_ci ixgbe_hwmon, 1998c2ecf20Sopenharmony_ci ixgbe_hwmon->groups); 2008c2ecf20Sopenharmony_ci if (IS_ERR(hwmon_dev)) 2018c2ecf20Sopenharmony_ci rc = PTR_ERR(hwmon_dev); 2028c2ecf20Sopenharmony_ciexit: 2038c2ecf20Sopenharmony_ci return rc; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 206