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 */
ixgbe_hwmon_show_location(struct device * dev,struct device_attribute * attr,char * buf)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
ixgbe_hwmon_show_temp(struct device * dev,struct device_attribute * attr,char * buf)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
ixgbe_hwmon_show_cautionthresh(struct device * dev,struct device_attribute * attr,char * buf)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
ixgbe_hwmon_show_maxopthresh(struct device * dev,struct device_attribute * attr,char * buf)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 */
ixgbe_add_hwmon_attr(struct ixgbe_adapter * adapter,unsigned int offset,int type)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
ixgbe_sysfs_del_adapter(struct ixgbe_adapter * adapter)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 */
ixgbe_sysfs_exit(struct ixgbe_adapter * adapter)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 */
ixgbe_sysfs_init(struct ixgbe_adapter * adapter)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