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