1/*******************************************************************************
2
3  Intel PRO/10GbE Linux driver
4  Copyright(c) 1999 - 2006 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  Linux NICS <linux.nics@intel.com>
24  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
25  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26
27*******************************************************************************/
28
29/* ethtool support for ixgb */
30
31#include "ixgb.h"
32
33#include <asm/uaccess.h>
34
35extern char ixgb_driver_name[];
36extern char ixgb_driver_version[];
37
38extern int ixgb_up(struct ixgb_adapter *adapter);
39extern void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog);
40extern void ixgb_reset(struct ixgb_adapter *adapter);
41extern int ixgb_setup_rx_resources(struct ixgb_adapter *adapter);
42extern int ixgb_setup_tx_resources(struct ixgb_adapter *adapter);
43extern void ixgb_free_rx_resources(struct ixgb_adapter *adapter);
44extern void ixgb_free_tx_resources(struct ixgb_adapter *adapter);
45extern void ixgb_update_stats(struct ixgb_adapter *adapter);
46
47#define IXGB_ALL_RAR_ENTRIES 16
48
49struct ixgb_stats {
50	char stat_string[ETH_GSTRING_LEN];
51	int sizeof_stat;
52	int stat_offset;
53};
54
55#define IXGB_STAT(m) sizeof(((struct ixgb_adapter *)0)->m), \
56		      offsetof(struct ixgb_adapter, m)
57static struct ixgb_stats ixgb_gstrings_stats[] = {
58	{"rx_packets", IXGB_STAT(net_stats.rx_packets)},
59	{"tx_packets", IXGB_STAT(net_stats.tx_packets)},
60	{"rx_bytes", IXGB_STAT(net_stats.rx_bytes)},
61	{"tx_bytes", IXGB_STAT(net_stats.tx_bytes)},
62	{"rx_errors", IXGB_STAT(net_stats.rx_errors)},
63	{"tx_errors", IXGB_STAT(net_stats.tx_errors)},
64	{"rx_dropped", IXGB_STAT(net_stats.rx_dropped)},
65	{"tx_dropped", IXGB_STAT(net_stats.tx_dropped)},
66	{"multicast", IXGB_STAT(net_stats.multicast)},
67	{"collisions", IXGB_STAT(net_stats.collisions)},
68
69/*	{ "rx_length_errors", IXGB_STAT(net_stats.rx_length_errors) },	*/
70	{"rx_over_errors", IXGB_STAT(net_stats.rx_over_errors)},
71	{"rx_crc_errors", IXGB_STAT(net_stats.rx_crc_errors)},
72	{"rx_frame_errors", IXGB_STAT(net_stats.rx_frame_errors)},
73	{"rx_fifo_errors", IXGB_STAT(net_stats.rx_fifo_errors)},
74	{"rx_missed_errors", IXGB_STAT(net_stats.rx_missed_errors)},
75	{"tx_aborted_errors", IXGB_STAT(net_stats.tx_aborted_errors)},
76	{"tx_carrier_errors", IXGB_STAT(net_stats.tx_carrier_errors)},
77	{"tx_fifo_errors", IXGB_STAT(net_stats.tx_fifo_errors)},
78	{"tx_heartbeat_errors", IXGB_STAT(net_stats.tx_heartbeat_errors)},
79	{"tx_window_errors", IXGB_STAT(net_stats.tx_window_errors)},
80	{"tx_deferred_ok", IXGB_STAT(stats.dc)},
81	{"tx_timeout_count", IXGB_STAT(tx_timeout_count) },
82	{"tx_restart_queue", IXGB_STAT(restart_queue) },
83	{"rx_long_length_errors", IXGB_STAT(stats.roc)},
84	{"rx_short_length_errors", IXGB_STAT(stats.ruc)},
85	{"tx_tcp_seg_good", IXGB_STAT(stats.tsctc)},
86	{"tx_tcp_seg_failed", IXGB_STAT(stats.tsctfc)},
87	{"rx_flow_control_xon", IXGB_STAT(stats.xonrxc)},
88	{"rx_flow_control_xoff", IXGB_STAT(stats.xoffrxc)},
89	{"tx_flow_control_xon", IXGB_STAT(stats.xontxc)},
90	{"tx_flow_control_xoff", IXGB_STAT(stats.xofftxc)},
91	{"rx_csum_offload_good", IXGB_STAT(hw_csum_rx_good)},
92	{"rx_csum_offload_errors", IXGB_STAT(hw_csum_rx_error)},
93	{"tx_csum_offload_good", IXGB_STAT(hw_csum_tx_good)},
94	{"tx_csum_offload_errors", IXGB_STAT(hw_csum_tx_error)}
95};
96
97#define IXGB_STATS_LEN	\
98	sizeof(ixgb_gstrings_stats) / sizeof(struct ixgb_stats)
99
100static int
101ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
102{
103	struct ixgb_adapter *adapter = netdev_priv(netdev);
104
105	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
106	ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
107	ecmd->port = PORT_FIBRE;
108	ecmd->transceiver = XCVR_EXTERNAL;
109
110	if(netif_carrier_ok(adapter->netdev)) {
111		ecmd->speed = SPEED_10000;
112		ecmd->duplex = DUPLEX_FULL;
113	} else {
114		ecmd->speed = -1;
115		ecmd->duplex = -1;
116	}
117
118	ecmd->autoneg = AUTONEG_DISABLE;
119	return 0;
120}
121
122static void ixgb_set_speed_duplex(struct net_device *netdev)
123{
124	struct ixgb_adapter *adapter = netdev_priv(netdev);
125	/* be optimistic about our link, since we were up before */
126	adapter->link_speed = 10000;
127	adapter->link_duplex = FULL_DUPLEX;
128	netif_carrier_on(netdev);
129	netif_wake_queue(netdev);
130}
131
132static int
133ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
134{
135	struct ixgb_adapter *adapter = netdev_priv(netdev);
136
137	if(ecmd->autoneg == AUTONEG_ENABLE ||
138	   ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
139		return -EINVAL;
140
141	if(netif_running(adapter->netdev)) {
142		ixgb_down(adapter, TRUE);
143		ixgb_reset(adapter);
144		ixgb_up(adapter);
145		ixgb_set_speed_duplex(netdev);
146	} else
147		ixgb_reset(adapter);
148
149	return 0;
150}
151
152static void
153ixgb_get_pauseparam(struct net_device *netdev,
154			 struct ethtool_pauseparam *pause)
155{
156	struct ixgb_adapter *adapter = netdev_priv(netdev);
157	struct ixgb_hw *hw = &adapter->hw;
158
159	pause->autoneg = AUTONEG_DISABLE;
160
161	if(hw->fc.type == ixgb_fc_rx_pause)
162		pause->rx_pause = 1;
163	else if(hw->fc.type == ixgb_fc_tx_pause)
164		pause->tx_pause = 1;
165	else if(hw->fc.type == ixgb_fc_full) {
166		pause->rx_pause = 1;
167		pause->tx_pause = 1;
168	}
169}
170
171static int
172ixgb_set_pauseparam(struct net_device *netdev,
173			 struct ethtool_pauseparam *pause)
174{
175	struct ixgb_adapter *adapter = netdev_priv(netdev);
176	struct ixgb_hw *hw = &adapter->hw;
177
178	if(pause->autoneg == AUTONEG_ENABLE)
179		return -EINVAL;
180
181	if(pause->rx_pause && pause->tx_pause)
182		hw->fc.type = ixgb_fc_full;
183	else if(pause->rx_pause && !pause->tx_pause)
184		hw->fc.type = ixgb_fc_rx_pause;
185	else if(!pause->rx_pause && pause->tx_pause)
186		hw->fc.type = ixgb_fc_tx_pause;
187	else if(!pause->rx_pause && !pause->tx_pause)
188		hw->fc.type = ixgb_fc_none;
189
190	if(netif_running(adapter->netdev)) {
191		ixgb_down(adapter, TRUE);
192		ixgb_up(adapter);
193		ixgb_set_speed_duplex(netdev);
194	} else
195		ixgb_reset(adapter);
196
197	return 0;
198}
199
200static uint32_t
201ixgb_get_rx_csum(struct net_device *netdev)
202{
203	struct ixgb_adapter *adapter = netdev_priv(netdev);
204
205	return adapter->rx_csum;
206}
207
208static int
209ixgb_set_rx_csum(struct net_device *netdev, uint32_t data)
210{
211	struct ixgb_adapter *adapter = netdev_priv(netdev);
212
213	adapter->rx_csum = data;
214
215	if(netif_running(netdev)) {
216		ixgb_down(adapter,TRUE);
217		ixgb_up(adapter);
218		ixgb_set_speed_duplex(netdev);
219	} else
220		ixgb_reset(adapter);
221	return 0;
222}
223
224static uint32_t
225ixgb_get_tx_csum(struct net_device *netdev)
226{
227	return (netdev->features & NETIF_F_HW_CSUM) != 0;
228}
229
230static int
231ixgb_set_tx_csum(struct net_device *netdev, uint32_t data)
232{
233	if (data)
234		netdev->features |= NETIF_F_HW_CSUM;
235	else
236		netdev->features &= ~NETIF_F_HW_CSUM;
237
238	return 0;
239}
240
241static int
242ixgb_set_tso(struct net_device *netdev, uint32_t data)
243{
244	if(data)
245		netdev->features |= NETIF_F_TSO;
246	else
247		netdev->features &= ~NETIF_F_TSO;
248	return 0;
249}
250
251static uint32_t
252ixgb_get_msglevel(struct net_device *netdev)
253{
254	struct ixgb_adapter *adapter = netdev_priv(netdev);
255	return adapter->msg_enable;
256}
257
258static void
259ixgb_set_msglevel(struct net_device *netdev, uint32_t data)
260{
261	struct ixgb_adapter *adapter = netdev_priv(netdev);
262	adapter->msg_enable = data;
263}
264#define IXGB_GET_STAT(_A_, _R_) _A_->stats._R_
265
266static int
267ixgb_get_regs_len(struct net_device *netdev)
268{
269#define IXGB_REG_DUMP_LEN  136*sizeof(uint32_t)
270	return IXGB_REG_DUMP_LEN;
271}
272
273static void
274ixgb_get_regs(struct net_device *netdev,
275		   struct ethtool_regs *regs, void *p)
276{
277	struct ixgb_adapter *adapter = netdev_priv(netdev);
278	struct ixgb_hw *hw = &adapter->hw;
279	uint32_t *reg = p;
280	uint32_t *reg_start = reg;
281	uint8_t i;
282
283	/* the 1 (one) below indicates an attempt at versioning, if the
284	 * interface in ethtool or the driver changes, this 1 should be
285	 * incremented */
286	regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id;
287
288	/* General Registers */
289	*reg++ = IXGB_READ_REG(hw, CTRL0);	/*   0 */
290	*reg++ = IXGB_READ_REG(hw, CTRL1);	/*   1 */
291	*reg++ = IXGB_READ_REG(hw, STATUS);	/*   2 */
292	*reg++ = IXGB_READ_REG(hw, EECD);	/*   3 */
293	*reg++ = IXGB_READ_REG(hw, MFS);	/*   4 */
294
295	/* Interrupt */
296	*reg++ = IXGB_READ_REG(hw, ICR);	/*   5 */
297	*reg++ = IXGB_READ_REG(hw, ICS);	/*   6 */
298	*reg++ = IXGB_READ_REG(hw, IMS);	/*   7 */
299	*reg++ = IXGB_READ_REG(hw, IMC);	/*   8 */
300
301	/* Receive */
302	*reg++ = IXGB_READ_REG(hw, RCTL);	/*   9 */
303	*reg++ = IXGB_READ_REG(hw, FCRTL);	/*  10 */
304	*reg++ = IXGB_READ_REG(hw, FCRTH);	/*  11 */
305	*reg++ = IXGB_READ_REG(hw, RDBAL);	/*  12 */
306	*reg++ = IXGB_READ_REG(hw, RDBAH);	/*  13 */
307	*reg++ = IXGB_READ_REG(hw, RDLEN);	/*  14 */
308	*reg++ = IXGB_READ_REG(hw, RDH);	/*  15 */
309	*reg++ = IXGB_READ_REG(hw, RDT);	/*  16 */
310	*reg++ = IXGB_READ_REG(hw, RDTR);	/*  17 */
311	*reg++ = IXGB_READ_REG(hw, RXDCTL);	/*  18 */
312	*reg++ = IXGB_READ_REG(hw, RAIDC);	/*  19 */
313	*reg++ = IXGB_READ_REG(hw, RXCSUM);	/*  20 */
314
315	/* there are 16 RAR entries in hardware, we only use 3 */
316	for(i = 0; i < IXGB_ALL_RAR_ENTRIES; i++) {
317		*reg++ = IXGB_READ_REG_ARRAY(hw, RAL, (i << 1)); /*21,...,51 */
318		*reg++ = IXGB_READ_REG_ARRAY(hw, RAH, (i << 1)); /*22,...,52 */
319	}
320
321	/* Transmit */
322	*reg++ = IXGB_READ_REG(hw, TCTL);	/*  53 */
323	*reg++ = IXGB_READ_REG(hw, TDBAL);	/*  54 */
324	*reg++ = IXGB_READ_REG(hw, TDBAH);	/*  55 */
325	*reg++ = IXGB_READ_REG(hw, TDLEN);	/*  56 */
326	*reg++ = IXGB_READ_REG(hw, TDH);	/*  57 */
327	*reg++ = IXGB_READ_REG(hw, TDT);	/*  58 */
328	*reg++ = IXGB_READ_REG(hw, TIDV);	/*  59 */
329	*reg++ = IXGB_READ_REG(hw, TXDCTL);	/*  60 */
330	*reg++ = IXGB_READ_REG(hw, TSPMT);	/*  61 */
331	*reg++ = IXGB_READ_REG(hw, PAP);	/*  62 */
332
333	/* Physical */
334	*reg++ = IXGB_READ_REG(hw, PCSC1);	/*  63 */
335	*reg++ = IXGB_READ_REG(hw, PCSC2);	/*  64 */
336	*reg++ = IXGB_READ_REG(hw, PCSS1);	/*  65 */
337	*reg++ = IXGB_READ_REG(hw, PCSS2);	/*  66 */
338	*reg++ = IXGB_READ_REG(hw, XPCSS);	/*  67 */
339	*reg++ = IXGB_READ_REG(hw, UCCR);	/*  68 */
340	*reg++ = IXGB_READ_REG(hw, XPCSTC);	/*  69 */
341	*reg++ = IXGB_READ_REG(hw, MACA);	/*  70 */
342	*reg++ = IXGB_READ_REG(hw, APAE);	/*  71 */
343	*reg++ = IXGB_READ_REG(hw, ARD);	/*  72 */
344	*reg++ = IXGB_READ_REG(hw, AIS);	/*  73 */
345	*reg++ = IXGB_READ_REG(hw, MSCA);	/*  74 */
346	*reg++ = IXGB_READ_REG(hw, MSRWD);	/*  75 */
347
348	/* Statistics */
349	*reg++ = IXGB_GET_STAT(adapter, tprl);	/*  76 */
350	*reg++ = IXGB_GET_STAT(adapter, tprh);	/*  77 */
351	*reg++ = IXGB_GET_STAT(adapter, gprcl);	/*  78 */
352	*reg++ = IXGB_GET_STAT(adapter, gprch);	/*  79 */
353	*reg++ = IXGB_GET_STAT(adapter, bprcl);	/*  80 */
354	*reg++ = IXGB_GET_STAT(adapter, bprch);	/*  81 */
355	*reg++ = IXGB_GET_STAT(adapter, mprcl);	/*  82 */
356	*reg++ = IXGB_GET_STAT(adapter, mprch);	/*  83 */
357	*reg++ = IXGB_GET_STAT(adapter, uprcl);	/*  84 */
358	*reg++ = IXGB_GET_STAT(adapter, uprch);	/*  85 */
359	*reg++ = IXGB_GET_STAT(adapter, vprcl);	/*  86 */
360	*reg++ = IXGB_GET_STAT(adapter, vprch);	/*  87 */
361	*reg++ = IXGB_GET_STAT(adapter, jprcl);	/*  88 */
362	*reg++ = IXGB_GET_STAT(adapter, jprch);	/*  89 */
363	*reg++ = IXGB_GET_STAT(adapter, gorcl);	/*  90 */
364	*reg++ = IXGB_GET_STAT(adapter, gorch);	/*  91 */
365	*reg++ = IXGB_GET_STAT(adapter, torl);	/*  92 */
366	*reg++ = IXGB_GET_STAT(adapter, torh);	/*  93 */
367	*reg++ = IXGB_GET_STAT(adapter, rnbc);	/*  94 */
368	*reg++ = IXGB_GET_STAT(adapter, ruc);	/*  95 */
369	*reg++ = IXGB_GET_STAT(adapter, roc);	/*  96 */
370	*reg++ = IXGB_GET_STAT(adapter, rlec);	/*  97 */
371	*reg++ = IXGB_GET_STAT(adapter, crcerrs);	/*  98 */
372	*reg++ = IXGB_GET_STAT(adapter, icbc);	/*  99 */
373	*reg++ = IXGB_GET_STAT(adapter, ecbc);	/* 100 */
374	*reg++ = IXGB_GET_STAT(adapter, mpc);	/* 101 */
375	*reg++ = IXGB_GET_STAT(adapter, tptl);	/* 102 */
376	*reg++ = IXGB_GET_STAT(adapter, tpth);	/* 103 */
377	*reg++ = IXGB_GET_STAT(adapter, gptcl);	/* 104 */
378	*reg++ = IXGB_GET_STAT(adapter, gptch);	/* 105 */
379	*reg++ = IXGB_GET_STAT(adapter, bptcl);	/* 106 */
380	*reg++ = IXGB_GET_STAT(adapter, bptch);	/* 107 */
381	*reg++ = IXGB_GET_STAT(adapter, mptcl);	/* 108 */
382	*reg++ = IXGB_GET_STAT(adapter, mptch);	/* 109 */
383	*reg++ = IXGB_GET_STAT(adapter, uptcl);	/* 110 */
384	*reg++ = IXGB_GET_STAT(adapter, uptch);	/* 111 */
385	*reg++ = IXGB_GET_STAT(adapter, vptcl);	/* 112 */
386	*reg++ = IXGB_GET_STAT(adapter, vptch);	/* 113 */
387	*reg++ = IXGB_GET_STAT(adapter, jptcl);	/* 114 */
388	*reg++ = IXGB_GET_STAT(adapter, jptch);	/* 115 */
389	*reg++ = IXGB_GET_STAT(adapter, gotcl);	/* 116 */
390	*reg++ = IXGB_GET_STAT(adapter, gotch);	/* 117 */
391	*reg++ = IXGB_GET_STAT(adapter, totl);	/* 118 */
392	*reg++ = IXGB_GET_STAT(adapter, toth);	/* 119 */
393	*reg++ = IXGB_GET_STAT(adapter, dc);	/* 120 */
394	*reg++ = IXGB_GET_STAT(adapter, plt64c);	/* 121 */
395	*reg++ = IXGB_GET_STAT(adapter, tsctc);	/* 122 */
396	*reg++ = IXGB_GET_STAT(adapter, tsctfc);	/* 123 */
397	*reg++ = IXGB_GET_STAT(adapter, ibic);	/* 124 */
398	*reg++ = IXGB_GET_STAT(adapter, rfc);	/* 125 */
399	*reg++ = IXGB_GET_STAT(adapter, lfc);	/* 126 */
400	*reg++ = IXGB_GET_STAT(adapter, pfrc);	/* 127 */
401	*reg++ = IXGB_GET_STAT(adapter, pftc);	/* 128 */
402	*reg++ = IXGB_GET_STAT(adapter, mcfrc);	/* 129 */
403	*reg++ = IXGB_GET_STAT(adapter, mcftc);	/* 130 */
404	*reg++ = IXGB_GET_STAT(adapter, xonrxc);	/* 131 */
405	*reg++ = IXGB_GET_STAT(adapter, xontxc);	/* 132 */
406	*reg++ = IXGB_GET_STAT(adapter, xoffrxc);	/* 133 */
407	*reg++ = IXGB_GET_STAT(adapter, xofftxc);	/* 134 */
408	*reg++ = IXGB_GET_STAT(adapter, rjc);	/* 135 */
409
410	regs->len = (reg - reg_start) * sizeof(uint32_t);
411}
412
413static int
414ixgb_get_eeprom_len(struct net_device *netdev)
415{
416	/* return size in bytes */
417	return (IXGB_EEPROM_SIZE << 1);
418}
419
420static int
421ixgb_get_eeprom(struct net_device *netdev,
422		  struct ethtool_eeprom *eeprom, uint8_t *bytes)
423{
424	struct ixgb_adapter *adapter = netdev_priv(netdev);
425	struct ixgb_hw *hw = &adapter->hw;
426	uint16_t *eeprom_buff;
427	int i, max_len, first_word, last_word;
428	int ret_val = 0;
429
430	if(eeprom->len == 0) {
431		ret_val = -EINVAL;
432		goto geeprom_error;
433	}
434
435	eeprom->magic = hw->vendor_id | (hw->device_id << 16);
436
437	max_len = ixgb_get_eeprom_len(netdev);
438
439	if(eeprom->offset > eeprom->offset + eeprom->len) {
440		ret_val = -EINVAL;
441		goto geeprom_error;
442	}
443
444	if((eeprom->offset + eeprom->len) > max_len)
445		eeprom->len = (max_len - eeprom->offset);
446
447	first_word = eeprom->offset >> 1;
448	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
449
450	eeprom_buff = kmalloc(sizeof(uint16_t) *
451			(last_word - first_word + 1), GFP_KERNEL);
452	if(!eeprom_buff)
453		return -ENOMEM;
454
455	/* note the eeprom was good because the driver loaded */
456	for(i = 0; i <= (last_word - first_word); i++) {
457		eeprom_buff[i] = ixgb_get_eeprom_word(hw, (first_word + i));
458	}
459
460	memcpy(bytes, (uint8_t *)eeprom_buff + (eeprom->offset & 1),
461			eeprom->len);
462	kfree(eeprom_buff);
463
464geeprom_error:
465	return ret_val;
466}
467
468static int
469ixgb_set_eeprom(struct net_device *netdev,
470		  struct ethtool_eeprom *eeprom, uint8_t *bytes)
471{
472	struct ixgb_adapter *adapter = netdev_priv(netdev);
473	struct ixgb_hw *hw = &adapter->hw;
474	uint16_t *eeprom_buff;
475	void *ptr;
476	int max_len, first_word, last_word;
477	uint16_t i;
478
479	if(eeprom->len == 0)
480		return -EINVAL;
481
482	if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16)))
483		return -EFAULT;
484
485	max_len = ixgb_get_eeprom_len(netdev);
486
487	if(eeprom->offset > eeprom->offset + eeprom->len)
488		return -EINVAL;
489
490	if((eeprom->offset + eeprom->len) > max_len)
491		eeprom->len = (max_len - eeprom->offset);
492
493	first_word = eeprom->offset >> 1;
494	last_word = (eeprom->offset + eeprom->len - 1) >> 1;
495	eeprom_buff = kmalloc(max_len, GFP_KERNEL);
496	if(!eeprom_buff)
497		return -ENOMEM;
498
499	ptr = (void *)eeprom_buff;
500
501	if(eeprom->offset & 1) {
502		/* need read/modify/write of first changed EEPROM word */
503		/* only the second byte of the word is being modified */
504		eeprom_buff[0] = ixgb_read_eeprom(hw, first_word);
505		ptr++;
506	}
507	if((eeprom->offset + eeprom->len) & 1) {
508		/* need read/modify/write of last changed EEPROM word */
509		/* only the first byte of the word is being modified */
510		eeprom_buff[last_word - first_word]
511			= ixgb_read_eeprom(hw, last_word);
512	}
513
514	memcpy(ptr, bytes, eeprom->len);
515	for(i = 0; i <= (last_word - first_word); i++)
516		ixgb_write_eeprom(hw, first_word + i, eeprom_buff[i]);
517
518	/* Update the checksum over the first part of the EEPROM if needed */
519	if(first_word <= EEPROM_CHECKSUM_REG)
520		ixgb_update_eeprom_checksum(hw);
521
522	kfree(eeprom_buff);
523	return 0;
524}
525
526static void
527ixgb_get_drvinfo(struct net_device *netdev,
528		   struct ethtool_drvinfo *drvinfo)
529{
530	struct ixgb_adapter *adapter = netdev_priv(netdev);
531
532	strncpy(drvinfo->driver,  ixgb_driver_name, 32);
533	strncpy(drvinfo->version, ixgb_driver_version, 32);
534	strncpy(drvinfo->fw_version, "N/A", 32);
535	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
536	drvinfo->n_stats = IXGB_STATS_LEN;
537	drvinfo->regdump_len = ixgb_get_regs_len(netdev);
538	drvinfo->eedump_len = ixgb_get_eeprom_len(netdev);
539}
540
541static void
542ixgb_get_ringparam(struct net_device *netdev,
543		struct ethtool_ringparam *ring)
544{
545	struct ixgb_adapter *adapter = netdev_priv(netdev);
546	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
547	struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
548
549	ring->rx_max_pending = MAX_RXD;
550	ring->tx_max_pending = MAX_TXD;
551	ring->rx_mini_max_pending = 0;
552	ring->rx_jumbo_max_pending = 0;
553	ring->rx_pending = rxdr->count;
554	ring->tx_pending = txdr->count;
555	ring->rx_mini_pending = 0;
556	ring->rx_jumbo_pending = 0;
557}
558
559static int
560ixgb_set_ringparam(struct net_device *netdev,
561		struct ethtool_ringparam *ring)
562{
563	struct ixgb_adapter *adapter = netdev_priv(netdev);
564	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
565	struct ixgb_desc_ring *rxdr = &adapter->rx_ring;
566	struct ixgb_desc_ring tx_old, tx_new, rx_old, rx_new;
567	int err;
568
569	tx_old = adapter->tx_ring;
570	rx_old = adapter->rx_ring;
571
572	if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
573		return -EINVAL;
574
575	if(netif_running(adapter->netdev))
576		ixgb_down(adapter,TRUE);
577
578	rxdr->count = max(ring->rx_pending,(uint32_t)MIN_RXD);
579	rxdr->count = min(rxdr->count,(uint32_t)MAX_RXD);
580	rxdr->count = ALIGN(rxdr->count, IXGB_REQ_RX_DESCRIPTOR_MULTIPLE);
581
582	txdr->count = max(ring->tx_pending,(uint32_t)MIN_TXD);
583	txdr->count = min(txdr->count,(uint32_t)MAX_TXD);
584	txdr->count = ALIGN(txdr->count, IXGB_REQ_TX_DESCRIPTOR_MULTIPLE);
585
586	if(netif_running(adapter->netdev)) {
587		/* Try to get new resources before deleting old */
588		if((err = ixgb_setup_rx_resources(adapter)))
589			goto err_setup_rx;
590		if((err = ixgb_setup_tx_resources(adapter)))
591			goto err_setup_tx;
592
593		/* save the new, restore the old in order to free it,
594		 * then restore the new back again */
595
596		rx_new = adapter->rx_ring;
597		tx_new = adapter->tx_ring;
598		adapter->rx_ring = rx_old;
599		adapter->tx_ring = tx_old;
600		ixgb_free_rx_resources(adapter);
601		ixgb_free_tx_resources(adapter);
602		adapter->rx_ring = rx_new;
603		adapter->tx_ring = tx_new;
604		if((err = ixgb_up(adapter)))
605			return err;
606		ixgb_set_speed_duplex(netdev);
607	}
608
609	return 0;
610err_setup_tx:
611	ixgb_free_rx_resources(adapter);
612err_setup_rx:
613	adapter->rx_ring = rx_old;
614	adapter->tx_ring = tx_old;
615	ixgb_up(adapter);
616	return err;
617}
618
619/* toggle LED 4 times per second = 2 "blinks" per second */
620#define IXGB_ID_INTERVAL	(HZ/4)
621
622/* bit defines for adapter->led_status */
623#define IXGB_LED_ON		0
624
625static void
626ixgb_led_blink_callback(unsigned long data)
627{
628	struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
629
630	if(test_and_change_bit(IXGB_LED_ON, &adapter->led_status))
631		ixgb_led_off(&adapter->hw);
632	else
633		ixgb_led_on(&adapter->hw);
634
635	mod_timer(&adapter->blink_timer, jiffies + IXGB_ID_INTERVAL);
636}
637
638static int
639ixgb_phys_id(struct net_device *netdev, uint32_t data)
640{
641	struct ixgb_adapter *adapter = netdev_priv(netdev);
642
643	if(!data || data > (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ))
644		data = (uint32_t)(MAX_SCHEDULE_TIMEOUT / HZ);
645
646	if(!adapter->blink_timer.function) {
647		init_timer(&adapter->blink_timer);
648		adapter->blink_timer.function = ixgb_led_blink_callback;
649		adapter->blink_timer.data = (unsigned long)adapter;
650	}
651
652	mod_timer(&adapter->blink_timer, jiffies);
653
654	msleep_interruptible(data * 1000);
655	del_timer_sync(&adapter->blink_timer);
656	ixgb_led_off(&adapter->hw);
657	clear_bit(IXGB_LED_ON, &adapter->led_status);
658
659	return 0;
660}
661
662static int
663ixgb_get_stats_count(struct net_device *netdev)
664{
665	return IXGB_STATS_LEN;
666}
667
668static void
669ixgb_get_ethtool_stats(struct net_device *netdev,
670		struct ethtool_stats *stats, uint64_t *data)
671{
672	struct ixgb_adapter *adapter = netdev_priv(netdev);
673	int i;
674
675	ixgb_update_stats(adapter);
676	for(i = 0; i < IXGB_STATS_LEN; i++) {
677		char *p = (char *)adapter+ixgb_gstrings_stats[i].stat_offset;
678		data[i] = (ixgb_gstrings_stats[i].sizeof_stat ==
679			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
680	}
681}
682
683static void
684ixgb_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
685{
686	int i;
687
688	switch(stringset) {
689	case ETH_SS_STATS:
690		for(i=0; i < IXGB_STATS_LEN; i++) {
691			memcpy(data + i * ETH_GSTRING_LEN,
692			ixgb_gstrings_stats[i].stat_string,
693			ETH_GSTRING_LEN);
694		}
695		break;
696	}
697}
698
699static const struct ethtool_ops ixgb_ethtool_ops = {
700	.get_settings = ixgb_get_settings,
701	.set_settings = ixgb_set_settings,
702	.get_drvinfo = ixgb_get_drvinfo,
703	.get_regs_len = ixgb_get_regs_len,
704	.get_regs = ixgb_get_regs,
705	.get_link = ethtool_op_get_link,
706	.get_eeprom_len = ixgb_get_eeprom_len,
707	.get_eeprom = ixgb_get_eeprom,
708	.set_eeprom = ixgb_set_eeprom,
709	.get_ringparam = ixgb_get_ringparam,
710	.set_ringparam = ixgb_set_ringparam,
711	.get_pauseparam	= ixgb_get_pauseparam,
712	.set_pauseparam	= ixgb_set_pauseparam,
713	.get_rx_csum = ixgb_get_rx_csum,
714	.set_rx_csum = ixgb_set_rx_csum,
715	.get_tx_csum = ixgb_get_tx_csum,
716	.set_tx_csum = ixgb_set_tx_csum,
717	.get_sg	= ethtool_op_get_sg,
718	.set_sg	= ethtool_op_set_sg,
719	.get_msglevel = ixgb_get_msglevel,
720	.set_msglevel = ixgb_set_msglevel,
721	.get_tso = ethtool_op_get_tso,
722	.set_tso = ixgb_set_tso,
723	.get_strings = ixgb_get_strings,
724	.phys_id = ixgb_phys_id,
725	.get_stats_count = ixgb_get_stats_count,
726	.get_ethtool_stats = ixgb_get_ethtool_stats,
727	.get_perm_addr = ethtool_op_get_perm_addr,
728};
729
730void ixgb_set_ethtool_ops(struct net_device *netdev)
731{
732	SET_ETHTOOL_OPS(netdev, &ixgb_ethtool_ops);
733}
734