Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 1999 - 2018 Intel Corporation. */
0003 
0004 #include "ixgbe.h"
0005 #include "ixgbe_common.h"
0006 #include "ixgbe_type.h"
0007 
0008 #include <linux/module.h>
0009 #include <linux/types.h>
0010 #include <linux/sysfs.h>
0011 #include <linux/kobject.h>
0012 #include <linux/device.h>
0013 #include <linux/netdevice.h>
0014 #include <linux/hwmon.h>
0015 
0016 /* hwmon callback functions */
0017 static ssize_t ixgbe_hwmon_show_location(struct device *dev,
0018                      struct device_attribute *attr,
0019                      char *buf)
0020 {
0021     struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
0022                              dev_attr);
0023     return sprintf(buf, "loc%u\n",
0024                ixgbe_attr->sensor->location);
0025 }
0026 
0027 static ssize_t ixgbe_hwmon_show_temp(struct device *dev,
0028                      struct device_attribute *attr,
0029                      char *buf)
0030 {
0031     struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
0032                              dev_attr);
0033     unsigned int value;
0034 
0035     /* reset the temp field */
0036     ixgbe_attr->hw->mac.ops.get_thermal_sensor_data(ixgbe_attr->hw);
0037 
0038     value = ixgbe_attr->sensor->temp;
0039 
0040     /* display millidegree */
0041     value *= 1000;
0042 
0043     return sprintf(buf, "%u\n", value);
0044 }
0045 
0046 static ssize_t ixgbe_hwmon_show_cautionthresh(struct device *dev,
0047                      struct device_attribute *attr,
0048                      char *buf)
0049 {
0050     struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
0051                              dev_attr);
0052     unsigned int value = ixgbe_attr->sensor->caution_thresh;
0053 
0054     /* display millidegree */
0055     value *= 1000;
0056 
0057     return sprintf(buf, "%u\n", value);
0058 }
0059 
0060 static ssize_t ixgbe_hwmon_show_maxopthresh(struct device *dev,
0061                      struct device_attribute *attr,
0062                      char *buf)
0063 {
0064     struct hwmon_attr *ixgbe_attr = container_of(attr, struct hwmon_attr,
0065                              dev_attr);
0066     unsigned int value = ixgbe_attr->sensor->max_op_thresh;
0067 
0068     /* display millidegree */
0069     value *= 1000;
0070 
0071     return sprintf(buf, "%u\n", value);
0072 }
0073 
0074 /**
0075  * ixgbe_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
0076  * @adapter: pointer to the adapter structure
0077  * @offset: offset in the eeprom sensor data table
0078  * @type: type of sensor data to display
0079  *
0080  * For each file we want in hwmon's sysfs interface we need a device_attribute
0081  * This is included in our hwmon_attr struct that contains the references to
0082  * the data structures we need to get the data to display.
0083  */
0084 static int ixgbe_add_hwmon_attr(struct ixgbe_adapter *adapter,
0085                 unsigned int offset, int type) {
0086     int rc;
0087     unsigned int n_attr;
0088     struct hwmon_attr *ixgbe_attr;
0089 
0090     n_attr = adapter->ixgbe_hwmon_buff->n_hwmon;
0091     ixgbe_attr = &adapter->ixgbe_hwmon_buff->hwmon_list[n_attr];
0092 
0093     switch (type) {
0094     case IXGBE_HWMON_TYPE_LOC:
0095         ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_location;
0096         snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
0097              "temp%u_label", offset + 1);
0098         break;
0099     case IXGBE_HWMON_TYPE_TEMP:
0100         ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_temp;
0101         snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
0102              "temp%u_input", offset + 1);
0103         break;
0104     case IXGBE_HWMON_TYPE_CAUTION:
0105         ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_cautionthresh;
0106         snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
0107              "temp%u_max", offset + 1);
0108         break;
0109     case IXGBE_HWMON_TYPE_MAX:
0110         ixgbe_attr->dev_attr.show = ixgbe_hwmon_show_maxopthresh;
0111         snprintf(ixgbe_attr->name, sizeof(ixgbe_attr->name),
0112              "temp%u_crit", offset + 1);
0113         break;
0114     default:
0115         rc = -EPERM;
0116         return rc;
0117     }
0118 
0119     /* These always the same regardless of type */
0120     ixgbe_attr->sensor =
0121         &adapter->hw.mac.thermal_sensor_data.sensor[offset];
0122     ixgbe_attr->hw = &adapter->hw;
0123     ixgbe_attr->dev_attr.store = NULL;
0124     ixgbe_attr->dev_attr.attr.mode = 0444;
0125     ixgbe_attr->dev_attr.attr.name = ixgbe_attr->name;
0126     sysfs_attr_init(&ixgbe_attr->dev_attr.attr);
0127 
0128     adapter->ixgbe_hwmon_buff->attrs[n_attr] = &ixgbe_attr->dev_attr.attr;
0129 
0130     ++adapter->ixgbe_hwmon_buff->n_hwmon;
0131 
0132     return 0;
0133 }
0134 
0135 static void ixgbe_sysfs_del_adapter(struct ixgbe_adapter *adapter)
0136 {
0137 }
0138 
0139 /* called from ixgbe_main.c */
0140 void ixgbe_sysfs_exit(struct ixgbe_adapter *adapter)
0141 {
0142     ixgbe_sysfs_del_adapter(adapter);
0143 }
0144 
0145 /* called from ixgbe_main.c */
0146 int ixgbe_sysfs_init(struct ixgbe_adapter *adapter)
0147 {
0148     struct hwmon_buff *ixgbe_hwmon;
0149     struct device *hwmon_dev;
0150     unsigned int i;
0151     int rc = 0;
0152 
0153     /* If this method isn't defined we don't support thermals */
0154     if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) {
0155         goto exit;
0156     }
0157 
0158     /* Don't create thermal hwmon interface if no sensors present */
0159     if (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw))
0160         goto exit;
0161 
0162     ixgbe_hwmon = devm_kzalloc(&adapter->pdev->dev, sizeof(*ixgbe_hwmon),
0163                    GFP_KERNEL);
0164     if (ixgbe_hwmon == NULL) {
0165         rc = -ENOMEM;
0166         goto exit;
0167     }
0168     adapter->ixgbe_hwmon_buff = ixgbe_hwmon;
0169 
0170     for (i = 0; i < IXGBE_MAX_SENSORS; i++) {
0171         /*
0172          * Only create hwmon sysfs entries for sensors that have
0173          * meaningful data for.
0174          */
0175         if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
0176             continue;
0177 
0178         /* Bail if any hwmon attr struct fails to initialize */
0179         rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_CAUTION);
0180         if (rc)
0181             goto exit;
0182         rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_LOC);
0183         if (rc)
0184             goto exit;
0185         rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_TEMP);
0186         if (rc)
0187             goto exit;
0188         rc = ixgbe_add_hwmon_attr(adapter, i, IXGBE_HWMON_TYPE_MAX);
0189         if (rc)
0190             goto exit;
0191     }
0192 
0193     ixgbe_hwmon->groups[0] = &ixgbe_hwmon->group;
0194     ixgbe_hwmon->group.attrs = ixgbe_hwmon->attrs;
0195 
0196     hwmon_dev = devm_hwmon_device_register_with_groups(&adapter->pdev->dev,
0197                                "ixgbe",
0198                                ixgbe_hwmon,
0199                                ixgbe_hwmon->groups);
0200     if (IS_ERR(hwmon_dev))
0201         rc = PTR_ERR(hwmon_dev);
0202 exit:
0203     return rc;
0204 }
0205