PageRenderTime 79ms CodeModel.GetById 3ms app.highlight 70ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c

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