linux/drivers/net/ethernet/intel/igb/igb_hwmon.c
<<
>>
Prefs
   1/*******************************************************************************
   2
   3  Intel(R) Gigabit Ethernet Linux driver
   4  Copyright(c) 2007-2013 Intel Corporation.
   5
   6  This program is free software; you can redistribute it and/or modify it
   7  under the terms and conditions of the GNU General Public License,
   8  version 2, as published by the Free Software Foundation.
   9
  10  This program is distributed in the hope it will be useful, but WITHOUT
  11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  13  more details.
  14
  15  You should have received a copy of the GNU General Public License along with
  16  this program; if not, write to the Free Software Foundation, Inc.,
  17  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  18
  19  The full GNU General Public License is included in this distribution in
  20  the file called "COPYING".
  21
  22  Contact Information:
  23  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
  24  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  25
  26*******************************************************************************/
  27
  28#include "igb.h"
  29#include "e1000_82575.h"
  30#include "e1000_hw.h"
  31
  32#include <linux/module.h>
  33#include <linux/types.h>
  34#include <linux/sysfs.h>
  35#include <linux/kobject.h>
  36#include <linux/device.h>
  37#include <linux/netdevice.h>
  38#include <linux/hwmon.h>
  39#include <linux/pci.h>
  40
  41#ifdef CONFIG_IGB_HWMON
  42static struct i2c_board_info i350_sensor_info = {
  43        I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)),
  44};
  45
  46/* hwmon callback functions */
  47static ssize_t igb_hwmon_show_location(struct device *dev,
  48                                       struct device_attribute *attr,
  49                                       char *buf)
  50{
  51        struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
  52                                                   dev_attr);
  53        return sprintf(buf, "loc%u\n",
  54                       igb_attr->sensor->location);
  55}
  56
  57static ssize_t igb_hwmon_show_temp(struct device *dev,
  58                                   struct device_attribute *attr,
  59                                   char *buf)
  60{
  61        struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
  62                                                   dev_attr);
  63        unsigned int value;
  64
  65        /* reset the temp field */
  66        igb_attr->hw->mac.ops.get_thermal_sensor_data(igb_attr->hw);
  67
  68        value = igb_attr->sensor->temp;
  69
  70        /* display millidegree */
  71        value *= 1000;
  72
  73        return sprintf(buf, "%u\n", value);
  74}
  75
  76static ssize_t igb_hwmon_show_cautionthresh(struct device *dev,
  77                                            struct device_attribute *attr,
  78                                            char *buf)
  79{
  80        struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
  81                                                   dev_attr);
  82        unsigned int value = igb_attr->sensor->caution_thresh;
  83
  84        /* display millidegree */
  85        value *= 1000;
  86
  87        return sprintf(buf, "%u\n", value);
  88}
  89
  90static ssize_t igb_hwmon_show_maxopthresh(struct device *dev,
  91                                          struct device_attribute *attr,
  92                                          char *buf)
  93{
  94        struct hwmon_attr *igb_attr = container_of(attr, struct hwmon_attr,
  95                                                   dev_attr);
  96        unsigned int value = igb_attr->sensor->max_op_thresh;
  97
  98        /* display millidegree */
  99        value *= 1000;
 100
 101        return sprintf(buf, "%u\n", value);
 102}
 103
 104/* igb_add_hwmon_attr - Create hwmon attr table for a hwmon sysfs file.
 105 * @ adapter: pointer to the adapter structure
 106 * @ offset: offset in the eeprom sensor data table
 107 * @ type: type of sensor data to display
 108 *
 109 * For each file we want in hwmon's sysfs interface we need a device_attribute
 110 * This is included in our hwmon_attr struct that contains the references to
 111 * the data structures we need to get the data to display.
 112 */
 113static int igb_add_hwmon_attr(struct igb_adapter *adapter,
 114                              unsigned int offset, int type)
 115{
 116        int rc;
 117        unsigned int n_attr;
 118        struct hwmon_attr *igb_attr;
 119
 120        n_attr = adapter->igb_hwmon_buff.n_hwmon;
 121        igb_attr = &adapter->igb_hwmon_buff.hwmon_list[n_attr];
 122
 123        switch (type) {
 124        case IGB_HWMON_TYPE_LOC:
 125                igb_attr->dev_attr.show = igb_hwmon_show_location;
 126                snprintf(igb_attr->name, sizeof(igb_attr->name),
 127                         "temp%u_label", offset);
 128                break;
 129        case IGB_HWMON_TYPE_TEMP:
 130                igb_attr->dev_attr.show = igb_hwmon_show_temp;
 131                snprintf(igb_attr->name, sizeof(igb_attr->name),
 132                         "temp%u_input", offset);
 133                break;
 134        case IGB_HWMON_TYPE_CAUTION:
 135                igb_attr->dev_attr.show = igb_hwmon_show_cautionthresh;
 136                snprintf(igb_attr->name, sizeof(igb_attr->name),
 137                         "temp%u_max", offset);
 138                break;
 139        case IGB_HWMON_TYPE_MAX:
 140                igb_attr->dev_attr.show = igb_hwmon_show_maxopthresh;
 141                snprintf(igb_attr->name, sizeof(igb_attr->name),
 142                         "temp%u_crit", offset);
 143                break;
 144        default:
 145                rc = -EPERM;
 146                return rc;
 147        }
 148
 149        /* These always the same regardless of type */
 150        igb_attr->sensor =
 151                &adapter->hw.mac.thermal_sensor_data.sensor[offset];
 152        igb_attr->hw = &adapter->hw;
 153        igb_attr->dev_attr.store = NULL;
 154        igb_attr->dev_attr.attr.mode = S_IRUGO;
 155        igb_attr->dev_attr.attr.name = igb_attr->name;
 156        sysfs_attr_init(&igb_attr->dev_attr.attr);
 157        rc = device_create_file(&adapter->pdev->dev,
 158                                &igb_attr->dev_attr);
 159        if (rc == 0)
 160                ++adapter->igb_hwmon_buff.n_hwmon;
 161
 162        return rc;
 163}
 164
 165static void igb_sysfs_del_adapter(struct igb_adapter *adapter)
 166{
 167        int i;
 168
 169        if (adapter == NULL)
 170                return;
 171
 172        for (i = 0; i < adapter->igb_hwmon_buff.n_hwmon; i++) {
 173                device_remove_file(&adapter->pdev->dev,
 174                           &adapter->igb_hwmon_buff.hwmon_list[i].dev_attr);
 175        }
 176
 177        kfree(adapter->igb_hwmon_buff.hwmon_list);
 178
 179        if (adapter->igb_hwmon_buff.device)
 180                hwmon_device_unregister(adapter->igb_hwmon_buff.device);
 181}
 182
 183/* called from igb_main.c */
 184void igb_sysfs_exit(struct igb_adapter *adapter)
 185{
 186        igb_sysfs_del_adapter(adapter);
 187}
 188
 189/* called from igb_main.c */
 190int igb_sysfs_init(struct igb_adapter *adapter)
 191{
 192        struct hwmon_buff *igb_hwmon = &adapter->igb_hwmon_buff;
 193        unsigned int i;
 194        int n_attrs;
 195        int rc = 0;
 196        struct i2c_client *client = NULL;
 197
 198        /* If this method isn't defined we don't support thermals */
 199        if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
 200                goto exit;
 201
 202        /* Don't create thermal hwmon interface if no sensors present */
 203        rc = (adapter->hw.mac.ops.init_thermal_sensor_thresh(&adapter->hw));
 204                if (rc)
 205                        goto exit;
 206
 207        /* init i2c_client */
 208        client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info);
 209        if (client == NULL) {
 210                dev_info(&adapter->pdev->dev,
 211                        "Failed to create new i2c device..\n");
 212                goto exit;
 213        }
 214        adapter->i2c_client = client;
 215
 216        /* Allocation space for max attributes
 217         * max num sensors * values (loc, temp, max, caution)
 218         */
 219        n_attrs = E1000_MAX_SENSORS * 4;
 220        igb_hwmon->hwmon_list = kcalloc(n_attrs, sizeof(struct hwmon_attr),
 221                                        GFP_KERNEL);
 222        if (!igb_hwmon->hwmon_list) {
 223                rc = -ENOMEM;
 224                goto err;
 225        }
 226
 227        igb_hwmon->device = hwmon_device_register(&adapter->pdev->dev);
 228        if (IS_ERR(igb_hwmon->device)) {
 229                rc = PTR_ERR(igb_hwmon->device);
 230                goto err;
 231        }
 232
 233        for (i = 0; i < E1000_MAX_SENSORS; i++) {
 234
 235                /* Only create hwmon sysfs entries for sensors that have
 236                 * meaningful data.
 237                 */
 238                if (adapter->hw.mac.thermal_sensor_data.sensor[i].location == 0)
 239                        continue;
 240
 241                /* Bail if any hwmon attr struct fails to initialize */
 242                rc = igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_CAUTION);
 243                rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_LOC);
 244                rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_TEMP);
 245                rc |= igb_add_hwmon_attr(adapter, i, IGB_HWMON_TYPE_MAX);
 246                if (rc)
 247                        goto err;
 248        }
 249
 250        goto exit;
 251
 252err:
 253        igb_sysfs_del_adapter(adapter);
 254exit:
 255        return rc;
 256}
 257#endif
 258