Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1/*******************************************************************************
  2
  3  Intel(R) 82576 Virtual Function Linux driver
  4  Copyright(c) 2009 - 2010 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/* ethtool support for igbvf */
 29
 30#include <linux/netdevice.h>
 31#include <linux/ethtool.h>
 32#include <linux/pci.h>
 33#include <linux/vmalloc.h>
 34#include <linux/delay.h>
 35
 36#include "igbvf.h"
 37#include <linux/if_vlan.h>
 38
 39
 40struct igbvf_stats {
 41	char stat_string[ETH_GSTRING_LEN];
 42	int sizeof_stat;
 43	int stat_offset;
 44	int base_stat_offset;
 45};
 46
 47#define IGBVF_STAT(current, base) \
 48		sizeof(((struct igbvf_adapter *)0)->current), \
 49		offsetof(struct igbvf_adapter, current), \
 50		offsetof(struct igbvf_adapter, base)
 51
 52static const struct igbvf_stats igbvf_gstrings_stats[] = {
 53	{ "rx_packets", IGBVF_STAT(stats.gprc, stats.base_gprc) },
 54	{ "tx_packets", IGBVF_STAT(stats.gptc, stats.base_gptc) },
 55	{ "rx_bytes", IGBVF_STAT(stats.gorc, stats.base_gorc) },
 56	{ "tx_bytes", IGBVF_STAT(stats.gotc, stats.base_gotc) },
 57	{ "multicast", IGBVF_STAT(stats.mprc, stats.base_mprc) },
 58	{ "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) },
 59	{ "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) },
 60	{ "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) },
 61	{ "rx_long_byte_count", IGBVF_STAT(stats.gorc, stats.base_gorc) },
 62	{ "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) },
 63	{ "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) },
 64	{ "rx_header_split", IGBVF_STAT(rx_hdr_split, zero_base) },
 65	{ "alloc_rx_buff_failed", IGBVF_STAT(alloc_rx_buff_failed, zero_base) },
 66};
 67
 68#define IGBVF_GLOBAL_STATS_LEN ARRAY_SIZE(igbvf_gstrings_stats)
 69
 70static const char igbvf_gstrings_test[][ETH_GSTRING_LEN] = {
 71	"Link test   (on/offline)"
 72};
 73
 74#define IGBVF_TEST_LEN ARRAY_SIZE(igbvf_gstrings_test)
 75
 76static int igbvf_get_settings(struct net_device *netdev,
 77                              struct ethtool_cmd *ecmd)
 78{
 79	struct igbvf_adapter *adapter = netdev_priv(netdev);
 80	struct e1000_hw *hw = &adapter->hw;
 81	u32 status;
 82
 83	ecmd->supported   = SUPPORTED_1000baseT_Full;
 84
 85	ecmd->advertising = ADVERTISED_1000baseT_Full;
 86
 87	ecmd->port = -1;
 88	ecmd->transceiver = XCVR_DUMMY1;
 89
 90	status = er32(STATUS);
 91	if (status & E1000_STATUS_LU) {
 92		if (status & E1000_STATUS_SPEED_1000)
 93			ethtool_cmd_speed_set(ecmd, SPEED_1000);
 94		else if (status & E1000_STATUS_SPEED_100)
 95			ethtool_cmd_speed_set(ecmd, SPEED_100);
 96		else
 97			ethtool_cmd_speed_set(ecmd, SPEED_10);
 98
 99		if (status & E1000_STATUS_FD)
100			ecmd->duplex = DUPLEX_FULL;
101		else
102			ecmd->duplex = DUPLEX_HALF;
103	} else {
104		ethtool_cmd_speed_set(ecmd, -1);
105		ecmd->duplex = -1;
106	}
107
108	ecmd->autoneg = AUTONEG_DISABLE;
109
110	return 0;
111}
112
113static int igbvf_set_settings(struct net_device *netdev,
114                              struct ethtool_cmd *ecmd)
115{
116	return -EOPNOTSUPP;
117}
118
119static void igbvf_get_pauseparam(struct net_device *netdev,
120                                 struct ethtool_pauseparam *pause)
121{
122	return;
123}
124
125static int igbvf_set_pauseparam(struct net_device *netdev,
126                                struct ethtool_pauseparam *pause)
127{
128	return -EOPNOTSUPP;
129}
130
131static u32 igbvf_get_rx_csum(struct net_device *netdev)
132{
133	struct igbvf_adapter *adapter = netdev_priv(netdev);
134	return !(adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED);
135}
136
137static int igbvf_set_rx_csum(struct net_device *netdev, u32 data)
138{
139	struct igbvf_adapter *adapter = netdev_priv(netdev);
140
141	if (data)
142		adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
143	else
144		adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
145
146	return 0;
147}
148
149static u32 igbvf_get_tx_csum(struct net_device *netdev)
150{
151	return (netdev->features & NETIF_F_IP_CSUM) != 0;
152}
153
154static int igbvf_set_tx_csum(struct net_device *netdev, u32 data)
155{
156	if (data)
157		netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
158	else
159		netdev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
160	return 0;
161}
162
163static int igbvf_set_tso(struct net_device *netdev, u32 data)
164{
165	struct igbvf_adapter *adapter = netdev_priv(netdev);
166
167	if (data) {
168		netdev->features |= NETIF_F_TSO;
169		netdev->features |= NETIF_F_TSO6;
170	} else {
171		netdev->features &= ~NETIF_F_TSO;
172		netdev->features &= ~NETIF_F_TSO6;
173	}
174
175	dev_info(&adapter->pdev->dev, "TSO is %s\n",
176	         data ? "Enabled" : "Disabled");
177	return 0;
178}
179
180static u32 igbvf_get_msglevel(struct net_device *netdev)
181{
182	struct igbvf_adapter *adapter = netdev_priv(netdev);
183	return adapter->msg_enable;
184}
185
186static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
187{
188	struct igbvf_adapter *adapter = netdev_priv(netdev);
189	adapter->msg_enable = data;
190}
191
192static int igbvf_get_regs_len(struct net_device *netdev)
193{
194#define IGBVF_REGS_LEN 8
195	return IGBVF_REGS_LEN * sizeof(u32);
196}
197
198static void igbvf_get_regs(struct net_device *netdev,
199                           struct ethtool_regs *regs, void *p)
200{
201	struct igbvf_adapter *adapter = netdev_priv(netdev);
202	struct e1000_hw *hw = &adapter->hw;
203	u32 *regs_buff = p;
204
205	memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
206
207	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
208			adapter->pdev->device;
209
210	regs_buff[0] = er32(CTRL);
211	regs_buff[1] = er32(STATUS);
212
213	regs_buff[2] = er32(RDLEN(0));
214	regs_buff[3] = er32(RDH(0));
215	regs_buff[4] = er32(RDT(0));
216
217	regs_buff[5] = er32(TDLEN(0));
218	regs_buff[6] = er32(TDH(0));
219	regs_buff[7] = er32(TDT(0));
220}
221
222static int igbvf_get_eeprom_len(struct net_device *netdev)
223{
224	return 0;
225}
226
227static int igbvf_get_eeprom(struct net_device *netdev,
228                            struct ethtool_eeprom *eeprom, u8 *bytes)
229{
230	return -EOPNOTSUPP;
231}
232
233static int igbvf_set_eeprom(struct net_device *netdev,
234                            struct ethtool_eeprom *eeprom, u8 *bytes)
235{
236	return -EOPNOTSUPP;
237}
238
239static void igbvf_get_drvinfo(struct net_device *netdev,
240                              struct ethtool_drvinfo *drvinfo)
241{
242	struct igbvf_adapter *adapter = netdev_priv(netdev);
243	char firmware_version[32] = "N/A";
244
245	strncpy(drvinfo->driver,  igbvf_driver_name, 32);
246	strncpy(drvinfo->version, igbvf_driver_version, 32);
247	strncpy(drvinfo->fw_version, firmware_version, 32);
248	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
249	drvinfo->regdump_len = igbvf_get_regs_len(netdev);
250	drvinfo->eedump_len = igbvf_get_eeprom_len(netdev);
251}
252
253static void igbvf_get_ringparam(struct net_device *netdev,
254                                struct ethtool_ringparam *ring)
255{
256	struct igbvf_adapter *adapter = netdev_priv(netdev);
257	struct igbvf_ring *tx_ring = adapter->tx_ring;
258	struct igbvf_ring *rx_ring = adapter->rx_ring;
259
260	ring->rx_max_pending = IGBVF_MAX_RXD;
261	ring->tx_max_pending = IGBVF_MAX_TXD;
262	ring->rx_mini_max_pending = 0;
263	ring->rx_jumbo_max_pending = 0;
264	ring->rx_pending = rx_ring->count;
265	ring->tx_pending = tx_ring->count;
266	ring->rx_mini_pending = 0;
267	ring->rx_jumbo_pending = 0;
268}
269
270static int igbvf_set_ringparam(struct net_device *netdev,
271                               struct ethtool_ringparam *ring)
272{
273	struct igbvf_adapter *adapter = netdev_priv(netdev);
274	struct igbvf_ring *temp_ring;
275	int err = 0;
276	u32 new_rx_count, new_tx_count;
277
278	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
279		return -EINVAL;
280
281	new_rx_count = max(ring->rx_pending, (u32)IGBVF_MIN_RXD);
282	new_rx_count = min(new_rx_count, (u32)IGBVF_MAX_RXD);
283	new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
284
285	new_tx_count = max(ring->tx_pending, (u32)IGBVF_MIN_TXD);
286	new_tx_count = min(new_tx_count, (u32)IGBVF_MAX_TXD);
287	new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
288
289	if ((new_tx_count == adapter->tx_ring->count) &&
290	    (new_rx_count == adapter->rx_ring->count)) {
291		/* nothing to do */
292		return 0;
293	}
294
295	while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
296		msleep(1);
297
298	if (!netif_running(adapter->netdev)) {
299		adapter->tx_ring->count = new_tx_count;
300		adapter->rx_ring->count = new_rx_count;
301		goto clear_reset;
302	}
303
304	temp_ring = vmalloc(sizeof(struct igbvf_ring));
305	if (!temp_ring) {
306		err = -ENOMEM;
307		goto clear_reset;
308	}
309
310	igbvf_down(adapter);
311
312	/*
313	 * We can't just free everything and then setup again,
314	 * because the ISRs in MSI-X mode get passed pointers
315	 * to the tx and rx ring structs.
316	 */
317	if (new_tx_count != adapter->tx_ring->count) {
318		memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
319
320		temp_ring->count = new_tx_count;
321		err = igbvf_setup_tx_resources(adapter, temp_ring);
322		if (err)
323			goto err_setup;
324
325		igbvf_free_tx_resources(adapter->tx_ring);
326
327		memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
328	}
329
330	if (new_rx_count != adapter->rx_ring->count) {
331		memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
332
333		temp_ring->count = new_rx_count;
334		err = igbvf_setup_rx_resources(adapter, temp_ring);
335		if (err)
336			goto err_setup;
337
338		igbvf_free_rx_resources(adapter->rx_ring);
339
340		memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
341	}
342err_setup:
343	igbvf_up(adapter);
344	vfree(temp_ring);
345clear_reset:
346	clear_bit(__IGBVF_RESETTING, &adapter->state);
347	return err;
348}
349
350static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
351{
352	struct e1000_hw *hw = &adapter->hw;
353	*data = 0;
354
355	hw->mac.ops.check_for_link(hw);
356
357	if (!(er32(STATUS) & E1000_STATUS_LU))
358		*data = 1;
359
360	return *data;
361}
362
363static void igbvf_diag_test(struct net_device *netdev,
364                            struct ethtool_test *eth_test, u64 *data)
365{
366	struct igbvf_adapter *adapter = netdev_priv(netdev);
367
368	set_bit(__IGBVF_TESTING, &adapter->state);
369
370	/*
371	 * Link test performed before hardware reset so autoneg doesn't
372	 * interfere with test result
373	 */
374	if (igbvf_link_test(adapter, &data[0]))
375		eth_test->flags |= ETH_TEST_FL_FAILED;
376
377	clear_bit(__IGBVF_TESTING, &adapter->state);
378	msleep_interruptible(4 * 1000);
379}
380
381static void igbvf_get_wol(struct net_device *netdev,
382                          struct ethtool_wolinfo *wol)
383{
384	wol->supported = 0;
385	wol->wolopts = 0;
386}
387
388static int igbvf_set_wol(struct net_device *netdev,
389                         struct ethtool_wolinfo *wol)
390{
391	return -EOPNOTSUPP;
392}
393
394static int igbvf_get_coalesce(struct net_device *netdev,
395                              struct ethtool_coalesce *ec)
396{
397	struct igbvf_adapter *adapter = netdev_priv(netdev);
398
399	if (adapter->itr_setting <= 3)
400		ec->rx_coalesce_usecs = adapter->itr_setting;
401	else
402		ec->rx_coalesce_usecs = adapter->itr_setting >> 2;
403
404	return 0;
405}
406
407static int igbvf_set_coalesce(struct net_device *netdev,
408                              struct ethtool_coalesce *ec)
409{
410	struct igbvf_adapter *adapter = netdev_priv(netdev);
411	struct e1000_hw *hw = &adapter->hw;
412
413	if ((ec->rx_coalesce_usecs > IGBVF_MAX_ITR_USECS) ||
414	    ((ec->rx_coalesce_usecs > 3) &&
415	     (ec->rx_coalesce_usecs < IGBVF_MIN_ITR_USECS)) ||
416	    (ec->rx_coalesce_usecs == 2))
417		return -EINVAL;
418
419	/* convert to rate of irq's per second */
420	if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) {
421		adapter->itr = IGBVF_START_ITR;
422		adapter->itr_setting = ec->rx_coalesce_usecs;
423	} else {
424		adapter->itr = ec->rx_coalesce_usecs << 2;
425		adapter->itr_setting = adapter->itr;
426	}
427
428	writel(adapter->itr,
429	       hw->hw_addr + adapter->rx_ring[0].itr_register);
430
431	return 0;
432}
433
434static int igbvf_nway_reset(struct net_device *netdev)
435{
436	struct igbvf_adapter *adapter = netdev_priv(netdev);
437	if (netif_running(netdev))
438		igbvf_reinit_locked(adapter);
439	return 0;
440}
441
442
443static void igbvf_get_ethtool_stats(struct net_device *netdev,
444                                    struct ethtool_stats *stats,
445                                    u64 *data)
446{
447	struct igbvf_adapter *adapter = netdev_priv(netdev);
448	int i;
449
450	igbvf_update_stats(adapter);
451	for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
452		char *p = (char *)adapter +
453		          igbvf_gstrings_stats[i].stat_offset;
454		char *b = (char *)adapter +
455		          igbvf_gstrings_stats[i].base_stat_offset;
456		data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
457		            sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
458		            (*(u32 *)p - *(u32 *)b));
459	}
460
461}
462
463static int igbvf_get_sset_count(struct net_device *dev, int stringset)
464{
465	switch(stringset) {
466	case ETH_SS_TEST:
467		return IGBVF_TEST_LEN;
468	case ETH_SS_STATS:
469		return IGBVF_GLOBAL_STATS_LEN;
470	default:
471		return -EINVAL;
472	}
473}
474
475static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
476                              u8 *data)
477{
478	u8 *p = data;
479	int i;
480
481	switch (stringset) {
482	case ETH_SS_TEST:
483		memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
484		break;
485	case ETH_SS_STATS:
486		for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
487			memcpy(p, igbvf_gstrings_stats[i].stat_string,
488			       ETH_GSTRING_LEN);
489			p += ETH_GSTRING_LEN;
490		}
491		break;
492	}
493}
494
495static const struct ethtool_ops igbvf_ethtool_ops = {
496	.get_settings		= igbvf_get_settings,
497	.set_settings		= igbvf_set_settings,
498	.get_drvinfo		= igbvf_get_drvinfo,
499	.get_regs_len		= igbvf_get_regs_len,
500	.get_regs		= igbvf_get_regs,
501	.get_wol		= igbvf_get_wol,
502	.set_wol		= igbvf_set_wol,
503	.get_msglevel		= igbvf_get_msglevel,
504	.set_msglevel		= igbvf_set_msglevel,
505	.nway_reset		= igbvf_nway_reset,
506	.get_link		= ethtool_op_get_link,
507	.get_eeprom_len		= igbvf_get_eeprom_len,
508	.get_eeprom		= igbvf_get_eeprom,
509	.set_eeprom		= igbvf_set_eeprom,
510	.get_ringparam		= igbvf_get_ringparam,
511	.set_ringparam		= igbvf_set_ringparam,
512	.get_pauseparam		= igbvf_get_pauseparam,
513	.set_pauseparam		= igbvf_set_pauseparam,
514	.get_rx_csum            = igbvf_get_rx_csum,
515	.set_rx_csum            = igbvf_set_rx_csum,
516	.get_tx_csum		= igbvf_get_tx_csum,
517	.set_tx_csum		= igbvf_set_tx_csum,
518	.get_sg			= ethtool_op_get_sg,
519	.set_sg			= ethtool_op_set_sg,
520	.get_tso		= ethtool_op_get_tso,
521	.set_tso		= igbvf_set_tso,
522	.self_test		= igbvf_diag_test,
523	.get_sset_count		= igbvf_get_sset_count,
524	.get_strings		= igbvf_get_strings,
525	.get_ethtool_stats	= igbvf_get_ethtool_stats,
526	.get_coalesce		= igbvf_get_coalesce,
527	.set_coalesce		= igbvf_set_coalesce,
528};
529
530void igbvf_set_ethtool_ops(struct net_device *netdev)
531{
532	/* have to "undeclare" const on this struct to remove warnings */
533	SET_ETHTOOL_OPS(netdev, (struct ethtool_ops *)&igbvf_ethtool_ops);
534}