1/******************************************************************************
2 * This software may be used and distributed according to the terms of
3 * the GNU General Public License (GPL), incorporated herein by reference.
4 * Drivers based on or derived from this code fall under the GPL and must
5 * retain the authorship, copyright and license notice.  This file is not
6 * a complete program and may only be used when the entire operating
7 * system is licensed under the GPL.
8 * See the file COPYING in this distribution for more information.
9 *
10 * vxge-ethtool.c: Driver for Exar Corp's X3100 Series 10GbE PCIe I/O
11 *                 Virtualized Server Adapter.
12 * Copyright(c) 2002-2010 Exar Corp.
13 ******************************************************************************/
14#include <linux/ethtool.h>
15#include <linux/slab.h>
16#include <linux/pci.h>
17#include <linux/etherdevice.h>
18
19#include "vxge-ethtool.h"
20
21static const char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = {
22	{"\n DRIVER STATISTICS"},
23	{"vpaths_opened"},
24	{"vpath_open_fail_cnt"},
25	{"link_up_cnt"},
26	{"link_down_cnt"},
27	{"tx_frms"},
28	{"tx_errors"},
29	{"tx_bytes"},
30	{"txd_not_free"},
31	{"txd_out_of_desc"},
32	{"rx_frms"},
33	{"rx_errors"},
34	{"rx_bytes"},
35	{"rx_mcast"},
36	{"pci_map_fail_cnt"},
37	{"skb_alloc_fail_cnt"}
38};
39
40/**
41 * vxge_ethtool_sset - Sets different link parameters.
42 * @dev: device pointer.
43 * @info: pointer to the structure with parameters given by ethtool to set
44 * link information.
45 *
46 * The function sets different link parameters provided by the user onto
47 * the NIC.
48 * Return value:
49 * 0 on success.
50 */
51static int vxge_ethtool_sset(struct net_device *dev, struct ethtool_cmd *info)
52{
53	/* We currently only support 10Gb/FULL */
54	if ((info->autoneg == AUTONEG_ENABLE) ||
55	    (ethtool_cmd_speed(info) != SPEED_10000) ||
56	    (info->duplex != DUPLEX_FULL))
57		return -EINVAL;
58
59	return 0;
60}
61
62/**
63 * vxge_ethtool_gset - Return link specific information.
64 * @dev: device pointer.
65 * @info: pointer to the structure with parameters given by ethtool
66 * to return link information.
67 *
68 * Returns link specific information like speed, duplex etc.. to ethtool.
69 * Return value :
70 * return 0 on success.
71 */
72static int vxge_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
73{
74	info->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
75	info->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
76	info->port = PORT_FIBRE;
77
78	info->transceiver = XCVR_EXTERNAL;
79
80	if (netif_carrier_ok(dev)) {
81		ethtool_cmd_speed_set(info, SPEED_10000);
82		info->duplex = DUPLEX_FULL;
83	} else {
84		ethtool_cmd_speed_set(info, SPEED_UNKNOWN);
85		info->duplex = DUPLEX_UNKNOWN;
86	}
87
88	info->autoneg = AUTONEG_DISABLE;
89	return 0;
90}
91
92/**
93 * vxge_ethtool_gdrvinfo - Returns driver specific information.
94 * @dev: device pointer.
95 * @info: pointer to the structure with parameters given by ethtool to
96 * return driver information.
97 *
98 * Returns driver specefic information like name, version etc.. to ethtool.
99 */
100static void vxge_ethtool_gdrvinfo(struct net_device *dev,
101				  struct ethtool_drvinfo *info)
102{
103	struct vxgedev *vdev = netdev_priv(dev);
104	strlcpy(info->driver, VXGE_DRIVER_NAME, sizeof(info->driver));
105	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
106	strlcpy(info->fw_version, vdev->fw_version, sizeof(info->fw_version));
107	strlcpy(info->bus_info, pci_name(vdev->pdev), sizeof(info->bus_info));
108	info->regdump_len = sizeof(struct vxge_hw_vpath_reg)
109				* vdev->no_of_vpath;
110
111	info->n_stats = STAT_LEN;
112}
113
114/**
115 * vxge_ethtool_gregs - dumps the entire space of Titan into the buffer.
116 * @dev: device pointer.
117 * @regs: pointer to the structure with parameters given by ethtool for
118 * dumping the registers.
119 * @reg_space: The input argumnet into which all the registers are dumped.
120 *
121 * Dumps the vpath register space of Titan NIC into the user given
122 * buffer area.
123 */
124static void vxge_ethtool_gregs(struct net_device *dev,
125			       struct ethtool_regs *regs, void *space)
126{
127	int index, offset;
128	enum vxge_hw_status status;
129	u64 reg;
130	u64 *reg_space = (u64 *)space;
131	struct vxgedev *vdev = netdev_priv(dev);
132	struct __vxge_hw_device *hldev = vdev->devh;
133
134	regs->len = sizeof(struct vxge_hw_vpath_reg) * vdev->no_of_vpath;
135	regs->version = vdev->pdev->subsystem_device;
136	for (index = 0; index < vdev->no_of_vpath; index++) {
137		for (offset = 0; offset < sizeof(struct vxge_hw_vpath_reg);
138				offset += 8) {
139			status = vxge_hw_mgmt_reg_read(hldev,
140					vxge_hw_mgmt_reg_type_vpath,
141					vdev->vpaths[index].device_id,
142					offset, &reg);
143			if (status != VXGE_HW_OK) {
144				vxge_debug_init(VXGE_ERR,
145					"%s:%d Getting reg dump Failed",
146						__func__, __LINE__);
147				return;
148			}
149			*reg_space++ = reg;
150		}
151	}
152}
153
154/**
155 * vxge_ethtool_idnic - To physically identify the nic on the system.
156 * @dev : device pointer.
157 * @state : requested LED state
158 *
159 * Used to physically identify the NIC on the system.
160 * 0 on success
161 */
162static int vxge_ethtool_idnic(struct net_device *dev,
163			      enum ethtool_phys_id_state state)
164{
165	struct vxgedev *vdev = netdev_priv(dev);
166	struct __vxge_hw_device *hldev = vdev->devh;
167
168	switch (state) {
169	case ETHTOOL_ID_ACTIVE:
170		vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_ON);
171		break;
172
173	case ETHTOOL_ID_INACTIVE:
174		vxge_hw_device_flick_link_led(hldev, VXGE_FLICKER_OFF);
175		break;
176
177	default:
178		return -EINVAL;
179	}
180
181	return 0;
182}
183
184/**
185 * vxge_ethtool_getpause_data - Pause frame frame generation and reception.
186 * @dev : device pointer.
187 * @ep : pointer to the structure with pause parameters given by ethtool.
188 * Description:
189 * Returns the Pause frame generation and reception capability of the NIC.
190 * Return value:
191 *  void
192 */
193static void vxge_ethtool_getpause_data(struct net_device *dev,
194				       struct ethtool_pauseparam *ep)
195{
196	struct vxgedev *vdev = netdev_priv(dev);
197	struct __vxge_hw_device *hldev = vdev->devh;
198
199	vxge_hw_device_getpause_data(hldev, 0, &ep->tx_pause, &ep->rx_pause);
200}
201
202/**
203 * vxge_ethtool_setpause_data -  set/reset pause frame generation.
204 * @dev : device pointer.
205 * @ep : pointer to the structure with pause parameters given by ethtool.
206 * Description:
207 * It can be used to set or reset Pause frame generation or reception
208 * support of the NIC.
209 * Return value:
210 * int, returns 0 on Success
211 */
212static int vxge_ethtool_setpause_data(struct net_device *dev,
213				      struct ethtool_pauseparam *ep)
214{
215	struct vxgedev *vdev = netdev_priv(dev);
216	struct __vxge_hw_device *hldev = vdev->devh;
217
218	vxge_hw_device_setpause_data(hldev, 0, ep->tx_pause, ep->rx_pause);
219
220	vdev->config.tx_pause_enable = ep->tx_pause;
221	vdev->config.rx_pause_enable = ep->rx_pause;
222
223	return 0;
224}
225
226static void vxge_get_ethtool_stats(struct net_device *dev,
227				   struct ethtool_stats *estats, u64 *tmp_stats)
228{
229	int j, k;
230	enum vxge_hw_status status;
231	enum vxge_hw_status swstatus;
232	struct vxge_vpath *vpath = NULL;
233	struct vxgedev *vdev = netdev_priv(dev);
234	struct __vxge_hw_device *hldev = vdev->devh;
235	struct vxge_hw_xmac_stats *xmac_stats;
236	struct vxge_hw_device_stats_sw_info *sw_stats;
237	struct vxge_hw_device_stats_hw_info *hw_stats;
238
239	u64 *ptr = tmp_stats;
240
241	memset(tmp_stats, 0,
242		vxge_ethtool_get_sset_count(dev, ETH_SS_STATS) * sizeof(u64));
243
244	xmac_stats = kzalloc(sizeof(struct vxge_hw_xmac_stats), GFP_KERNEL);
245	if (xmac_stats == NULL) {
246		vxge_debug_init(VXGE_ERR,
247			"%s : %d Memory Allocation failed for xmac_stats",
248				 __func__, __LINE__);
249		return;
250	}
251
252	sw_stats = kzalloc(sizeof(struct vxge_hw_device_stats_sw_info),
253				GFP_KERNEL);
254	if (sw_stats == NULL) {
255		kfree(xmac_stats);
256		vxge_debug_init(VXGE_ERR,
257			"%s : %d Memory Allocation failed for sw_stats",
258			__func__, __LINE__);
259		return;
260	}
261
262	hw_stats = kzalloc(sizeof(struct vxge_hw_device_stats_hw_info),
263				GFP_KERNEL);
264	if (hw_stats == NULL) {
265		kfree(xmac_stats);
266		kfree(sw_stats);
267		vxge_debug_init(VXGE_ERR,
268			"%s : %d Memory Allocation failed for hw_stats",
269			__func__, __LINE__);
270		return;
271	}
272
273	*ptr++ = 0;
274	status = vxge_hw_device_xmac_stats_get(hldev, xmac_stats);
275	if (status != VXGE_HW_OK) {
276		if (status != VXGE_HW_ERR_PRIVILAGED_OPEARATION) {
277			vxge_debug_init(VXGE_ERR,
278				"%s : %d Failure in getting xmac stats",
279				__func__, __LINE__);
280		}
281	}
282	swstatus = vxge_hw_driver_stats_get(hldev, sw_stats);
283	if (swstatus != VXGE_HW_OK) {
284		vxge_debug_init(VXGE_ERR,
285			"%s : %d Failure in getting sw stats",
286			__func__, __LINE__);
287	}
288
289	status = vxge_hw_device_stats_get(hldev, hw_stats);
290	if (status != VXGE_HW_OK) {
291		vxge_debug_init(VXGE_ERR,
292			"%s : %d hw_stats_get error", __func__, __LINE__);
293	}
294
295	for (k = 0; k < vdev->no_of_vpath; k++) {
296		struct vxge_hw_vpath_stats_hw_info *vpath_info;
297
298		vpath = &vdev->vpaths[k];
299		j = vpath->device_id;
300		vpath_info = hw_stats->vpath_info[j];
301		if (!vpath_info) {
302			memset(ptr, 0, (VXGE_HW_VPATH_TX_STATS_LEN +
303				VXGE_HW_VPATH_RX_STATS_LEN) * sizeof(u64));
304			ptr += (VXGE_HW_VPATH_TX_STATS_LEN +
305				VXGE_HW_VPATH_RX_STATS_LEN);
306			continue;
307		}
308
309		*ptr++ = vpath_info->tx_stats.tx_ttl_eth_frms;
310		*ptr++ = vpath_info->tx_stats.tx_ttl_eth_octets;
311		*ptr++ = vpath_info->tx_stats.tx_data_octets;
312		*ptr++ = vpath_info->tx_stats.tx_mcast_frms;
313		*ptr++ = vpath_info->tx_stats.tx_bcast_frms;
314		*ptr++ = vpath_info->tx_stats.tx_ucast_frms;
315		*ptr++ = vpath_info->tx_stats.tx_tagged_frms;
316		*ptr++ = vpath_info->tx_stats.tx_vld_ip;
317		*ptr++ = vpath_info->tx_stats.tx_vld_ip_octets;
318		*ptr++ = vpath_info->tx_stats.tx_icmp;
319		*ptr++ = vpath_info->tx_stats.tx_tcp;
320		*ptr++ = vpath_info->tx_stats.tx_rst_tcp;
321		*ptr++ = vpath_info->tx_stats.tx_udp;
322		*ptr++ = vpath_info->tx_stats.tx_unknown_protocol;
323		*ptr++ = vpath_info->tx_stats.tx_lost_ip;
324		*ptr++ = vpath_info->tx_stats.tx_parse_error;
325		*ptr++ = vpath_info->tx_stats.tx_tcp_offload;
326		*ptr++ = vpath_info->tx_stats.tx_retx_tcp_offload;
327		*ptr++ = vpath_info->tx_stats.tx_lost_ip_offload;
328		*ptr++ = vpath_info->rx_stats.rx_ttl_eth_frms;
329		*ptr++ = vpath_info->rx_stats.rx_vld_frms;
330		*ptr++ = vpath_info->rx_stats.rx_offload_frms;
331		*ptr++ = vpath_info->rx_stats.rx_ttl_eth_octets;
332		*ptr++ = vpath_info->rx_stats.rx_data_octets;
333		*ptr++ = vpath_info->rx_stats.rx_offload_octets;
334		*ptr++ = vpath_info->rx_stats.rx_vld_mcast_frms;
335		*ptr++ = vpath_info->rx_stats.rx_vld_bcast_frms;
336		*ptr++ = vpath_info->rx_stats.rx_accepted_ucast_frms;
337		*ptr++ = vpath_info->rx_stats.rx_accepted_nucast_frms;
338		*ptr++ = vpath_info->rx_stats.rx_tagged_frms;
339		*ptr++ = vpath_info->rx_stats.rx_long_frms;
340		*ptr++ = vpath_info->rx_stats.rx_usized_frms;
341		*ptr++ = vpath_info->rx_stats.rx_osized_frms;
342		*ptr++ = vpath_info->rx_stats.rx_frag_frms;
343		*ptr++ = vpath_info->rx_stats.rx_jabber_frms;
344		*ptr++ = vpath_info->rx_stats.rx_ttl_64_frms;
345		*ptr++ = vpath_info->rx_stats.rx_ttl_65_127_frms;
346		*ptr++ = vpath_info->rx_stats.rx_ttl_128_255_frms;
347		*ptr++ = vpath_info->rx_stats.rx_ttl_256_511_frms;
348		*ptr++ = vpath_info->rx_stats.rx_ttl_512_1023_frms;
349		*ptr++ = vpath_info->rx_stats.rx_ttl_1024_1518_frms;
350		*ptr++ = vpath_info->rx_stats.rx_ttl_1519_4095_frms;
351		*ptr++ = vpath_info->rx_stats.rx_ttl_4096_8191_frms;
352		*ptr++ = vpath_info->rx_stats.rx_ttl_8192_max_frms;
353		*ptr++ = vpath_info->rx_stats.rx_ttl_gt_max_frms;
354		*ptr++ = vpath_info->rx_stats.rx_ip;
355		*ptr++ = vpath_info->rx_stats.rx_accepted_ip;
356		*ptr++ = vpath_info->rx_stats.rx_ip_octets;
357		*ptr++ = vpath_info->rx_stats.rx_err_ip;
358		*ptr++ = vpath_info->rx_stats.rx_icmp;
359		*ptr++ = vpath_info->rx_stats.rx_tcp;
360		*ptr++ = vpath_info->rx_stats.rx_udp;
361		*ptr++ = vpath_info->rx_stats.rx_err_tcp;
362		*ptr++ = vpath_info->rx_stats.rx_lost_frms;
363		*ptr++ = vpath_info->rx_stats.rx_lost_ip;
364		*ptr++ = vpath_info->rx_stats.rx_lost_ip_offload;
365		*ptr++ = vpath_info->rx_stats.rx_various_discard;
366		*ptr++ = vpath_info->rx_stats.rx_sleep_discard;
367		*ptr++ = vpath_info->rx_stats.rx_red_discard;
368		*ptr++ = vpath_info->rx_stats.rx_queue_full_discard;
369		*ptr++ = vpath_info->rx_stats.rx_mpa_ok_frms;
370	}
371	*ptr++ = 0;
372	for (k = 0; k < vdev->max_config_port; k++) {
373		*ptr++ = xmac_stats->aggr_stats[k].tx_frms;
374		*ptr++ = xmac_stats->aggr_stats[k].tx_data_octets;
375		*ptr++ = xmac_stats->aggr_stats[k].tx_mcast_frms;
376		*ptr++ = xmac_stats->aggr_stats[k].tx_bcast_frms;
377		*ptr++ = xmac_stats->aggr_stats[k].tx_discarded_frms;
378		*ptr++ = xmac_stats->aggr_stats[k].tx_errored_frms;
379		*ptr++ = xmac_stats->aggr_stats[k].rx_frms;
380		*ptr++ = xmac_stats->aggr_stats[k].rx_data_octets;
381		*ptr++ = xmac_stats->aggr_stats[k].rx_mcast_frms;
382		*ptr++ = xmac_stats->aggr_stats[k].rx_bcast_frms;
383		*ptr++ = xmac_stats->aggr_stats[k].rx_discarded_frms;
384		*ptr++ = xmac_stats->aggr_stats[k].rx_errored_frms;
385		*ptr++ = xmac_stats->aggr_stats[k].rx_unknown_slow_proto_frms;
386	}
387	*ptr++ = 0;
388	for (k = 0; k < vdev->max_config_port; k++) {
389		*ptr++ = xmac_stats->port_stats[k].tx_ttl_frms;
390		*ptr++ = xmac_stats->port_stats[k].tx_ttl_octets;
391		*ptr++ = xmac_stats->port_stats[k].tx_data_octets;
392		*ptr++ = xmac_stats->port_stats[k].tx_mcast_frms;
393		*ptr++ = xmac_stats->port_stats[k].tx_bcast_frms;
394		*ptr++ = xmac_stats->port_stats[k].tx_ucast_frms;
395		*ptr++ = xmac_stats->port_stats[k].tx_tagged_frms;
396		*ptr++ = xmac_stats->port_stats[k].tx_vld_ip;
397		*ptr++ = xmac_stats->port_stats[k].tx_vld_ip_octets;
398		*ptr++ = xmac_stats->port_stats[k].tx_icmp;
399		*ptr++ = xmac_stats->port_stats[k].tx_tcp;
400		*ptr++ = xmac_stats->port_stats[k].tx_rst_tcp;
401		*ptr++ = xmac_stats->port_stats[k].tx_udp;
402		*ptr++ = xmac_stats->port_stats[k].tx_parse_error;
403		*ptr++ = xmac_stats->port_stats[k].tx_unknown_protocol;
404		*ptr++ = xmac_stats->port_stats[k].tx_pause_ctrl_frms;
405		*ptr++ = xmac_stats->port_stats[k].tx_marker_pdu_frms;
406		*ptr++ = xmac_stats->port_stats[k].tx_lacpdu_frms;
407		*ptr++ = xmac_stats->port_stats[k].tx_drop_ip;
408		*ptr++ = xmac_stats->port_stats[k].tx_marker_resp_pdu_frms;
409		*ptr++ = xmac_stats->port_stats[k].tx_xgmii_char2_match;
410		*ptr++ = xmac_stats->port_stats[k].tx_xgmii_char1_match;
411		*ptr++ = xmac_stats->port_stats[k].tx_xgmii_column2_match;
412		*ptr++ = xmac_stats->port_stats[k].tx_xgmii_column1_match;
413		*ptr++ = xmac_stats->port_stats[k].tx_any_err_frms;
414		*ptr++ = xmac_stats->port_stats[k].tx_drop_frms;
415		*ptr++ = xmac_stats->port_stats[k].rx_ttl_frms;
416		*ptr++ = xmac_stats->port_stats[k].rx_vld_frms;
417		*ptr++ = xmac_stats->port_stats[k].rx_offload_frms;
418		*ptr++ = xmac_stats->port_stats[k].rx_ttl_octets;
419		*ptr++ = xmac_stats->port_stats[k].rx_data_octets;
420		*ptr++ = xmac_stats->port_stats[k].rx_offload_octets;
421		*ptr++ = xmac_stats->port_stats[k].rx_vld_mcast_frms;
422		*ptr++ = xmac_stats->port_stats[k].rx_vld_bcast_frms;
423		*ptr++ = xmac_stats->port_stats[k].rx_accepted_ucast_frms;
424		*ptr++ = xmac_stats->port_stats[k].rx_accepted_nucast_frms;
425		*ptr++ = xmac_stats->port_stats[k].rx_tagged_frms;
426		*ptr++ = xmac_stats->port_stats[k].rx_long_frms;
427		*ptr++ = xmac_stats->port_stats[k].rx_usized_frms;
428		*ptr++ = xmac_stats->port_stats[k].rx_osized_frms;
429		*ptr++ = xmac_stats->port_stats[k].rx_frag_frms;
430		*ptr++ = xmac_stats->port_stats[k].rx_jabber_frms;
431		*ptr++ = xmac_stats->port_stats[k].rx_ttl_64_frms;
432		*ptr++ = xmac_stats->port_stats[k].rx_ttl_65_127_frms;
433		*ptr++ = xmac_stats->port_stats[k].rx_ttl_128_255_frms;
434		*ptr++ = xmac_stats->port_stats[k].rx_ttl_256_511_frms;
435		*ptr++ = xmac_stats->port_stats[k].rx_ttl_512_1023_frms;
436		*ptr++ = xmac_stats->port_stats[k].rx_ttl_1024_1518_frms;
437		*ptr++ = xmac_stats->port_stats[k].rx_ttl_1519_4095_frms;
438		*ptr++ = xmac_stats->port_stats[k].rx_ttl_4096_8191_frms;
439		*ptr++ = xmac_stats->port_stats[k].rx_ttl_8192_max_frms;
440		*ptr++ = xmac_stats->port_stats[k].rx_ttl_gt_max_frms;
441		*ptr++ = xmac_stats->port_stats[k].rx_ip;
442		*ptr++ = xmac_stats->port_stats[k].rx_accepted_ip;
443		*ptr++ = xmac_stats->port_stats[k].rx_ip_octets;
444		*ptr++ = xmac_stats->port_stats[k].rx_err_ip;
445		*ptr++ = xmac_stats->port_stats[k].rx_icmp;
446		*ptr++ = xmac_stats->port_stats[k].rx_tcp;
447		*ptr++ = xmac_stats->port_stats[k].rx_udp;
448		*ptr++ = xmac_stats->port_stats[k].rx_err_tcp;
449		*ptr++ = xmac_stats->port_stats[k].rx_pause_count;
450		*ptr++ = xmac_stats->port_stats[k].rx_pause_ctrl_frms;
451		*ptr++ = xmac_stats->port_stats[k].rx_unsup_ctrl_frms;
452		*ptr++ = xmac_stats->port_stats[k].rx_fcs_err_frms;
453		*ptr++ = xmac_stats->port_stats[k].rx_in_rng_len_err_frms;
454		*ptr++ = xmac_stats->port_stats[k].rx_out_rng_len_err_frms;
455		*ptr++ = xmac_stats->port_stats[k].rx_drop_frms;
456		*ptr++ = xmac_stats->port_stats[k].rx_discarded_frms;
457		*ptr++ = xmac_stats->port_stats[k].rx_drop_ip;
458		*ptr++ = xmac_stats->port_stats[k].rx_drop_udp;
459		*ptr++ = xmac_stats->port_stats[k].rx_marker_pdu_frms;
460		*ptr++ = xmac_stats->port_stats[k].rx_lacpdu_frms;
461		*ptr++ = xmac_stats->port_stats[k].rx_unknown_pdu_frms;
462		*ptr++ = xmac_stats->port_stats[k].rx_marker_resp_pdu_frms;
463		*ptr++ = xmac_stats->port_stats[k].rx_fcs_discard;
464		*ptr++ = xmac_stats->port_stats[k].rx_illegal_pdu_frms;
465		*ptr++ = xmac_stats->port_stats[k].rx_switch_discard;
466		*ptr++ = xmac_stats->port_stats[k].rx_len_discard;
467		*ptr++ = xmac_stats->port_stats[k].rx_rpa_discard;
468		*ptr++ = xmac_stats->port_stats[k].rx_l2_mgmt_discard;
469		*ptr++ = xmac_stats->port_stats[k].rx_rts_discard;
470		*ptr++ = xmac_stats->port_stats[k].rx_trash_discard;
471		*ptr++ = xmac_stats->port_stats[k].rx_buff_full_discard;
472		*ptr++ = xmac_stats->port_stats[k].rx_red_discard;
473		*ptr++ = xmac_stats->port_stats[k].rx_xgmii_ctrl_err_cnt;
474		*ptr++ = xmac_stats->port_stats[k].rx_xgmii_data_err_cnt;
475		*ptr++ = xmac_stats->port_stats[k].rx_xgmii_char1_match;
476		*ptr++ = xmac_stats->port_stats[k].rx_xgmii_err_sym;
477		*ptr++ = xmac_stats->port_stats[k].rx_xgmii_column1_match;
478		*ptr++ = xmac_stats->port_stats[k].rx_xgmii_char2_match;
479		*ptr++ = xmac_stats->port_stats[k].rx_local_fault;
480		*ptr++ = xmac_stats->port_stats[k].rx_xgmii_column2_match;
481		*ptr++ = xmac_stats->port_stats[k].rx_jettison;
482		*ptr++ = xmac_stats->port_stats[k].rx_remote_fault;
483	}
484
485	*ptr++ = 0;
486	for (k = 0; k < vdev->no_of_vpath; k++) {
487		struct vxge_hw_vpath_stats_sw_info *vpath_info;
488
489		vpath = &vdev->vpaths[k];
490		j = vpath->device_id;
491		vpath_info = (struct vxge_hw_vpath_stats_sw_info *)
492				&sw_stats->vpath_info[j];
493		*ptr++ = vpath_info->soft_reset_cnt;
494		*ptr++ = vpath_info->error_stats.unknown_alarms;
495		*ptr++ = vpath_info->error_stats.network_sustained_fault;
496		*ptr++ = vpath_info->error_stats.network_sustained_ok;
497		*ptr++ = vpath_info->error_stats.kdfcctl_fifo0_overwrite;
498		*ptr++ = vpath_info->error_stats.kdfcctl_fifo0_poison;
499		*ptr++ = vpath_info->error_stats.kdfcctl_fifo0_dma_error;
500		*ptr++ = vpath_info->error_stats.dblgen_fifo0_overflow;
501		*ptr++ = vpath_info->error_stats.statsb_pif_chain_error;
502		*ptr++ = vpath_info->error_stats.statsb_drop_timeout;
503		*ptr++ = vpath_info->error_stats.target_illegal_access;
504		*ptr++ = vpath_info->error_stats.ini_serr_det;
505		*ptr++ = vpath_info->error_stats.prc_ring_bumps;
506		*ptr++ = vpath_info->error_stats.prc_rxdcm_sc_err;
507		*ptr++ = vpath_info->error_stats.prc_rxdcm_sc_abort;
508		*ptr++ = vpath_info->error_stats.prc_quanta_size_err;
509		*ptr++ = vpath_info->ring_stats.common_stats.full_cnt;
510		*ptr++ = vpath_info->ring_stats.common_stats.usage_cnt;
511		*ptr++ = vpath_info->ring_stats.common_stats.usage_max;
512		*ptr++ = vpath_info->ring_stats.common_stats.
513					reserve_free_swaps_cnt;
514		*ptr++ = vpath_info->ring_stats.common_stats.total_compl_cnt;
515		for (j = 0; j < VXGE_HW_DTR_MAX_T_CODE; j++)
516			*ptr++ = vpath_info->ring_stats.rxd_t_code_err_cnt[j];
517		*ptr++ = vpath_info->fifo_stats.common_stats.full_cnt;
518		*ptr++ = vpath_info->fifo_stats.common_stats.usage_cnt;
519		*ptr++ = vpath_info->fifo_stats.common_stats.usage_max;
520		*ptr++ = vpath_info->fifo_stats.common_stats.
521						reserve_free_swaps_cnt;
522		*ptr++ = vpath_info->fifo_stats.common_stats.total_compl_cnt;
523		*ptr++ = vpath_info->fifo_stats.total_posts;
524		*ptr++ = vpath_info->fifo_stats.total_buffers;
525		for (j = 0; j < VXGE_HW_DTR_MAX_T_CODE; j++)
526			*ptr++ = vpath_info->fifo_stats.txd_t_code_err_cnt[j];
527	}
528
529	*ptr++ = 0;
530	for (k = 0; k < vdev->no_of_vpath; k++) {
531		struct vxge_hw_vpath_stats_hw_info *vpath_info;
532		vpath = &vdev->vpaths[k];
533		j = vpath->device_id;
534		vpath_info = hw_stats->vpath_info[j];
535		if (!vpath_info) {
536			memset(ptr, 0, VXGE_HW_VPATH_STATS_LEN * sizeof(u64));
537			ptr += VXGE_HW_VPATH_STATS_LEN;
538			continue;
539		}
540		*ptr++ = vpath_info->ini_num_mwr_sent;
541		*ptr++ = vpath_info->ini_num_mrd_sent;
542		*ptr++ = vpath_info->ini_num_cpl_rcvd;
543		*ptr++ = vpath_info->ini_num_mwr_byte_sent;
544		*ptr++ = vpath_info->ini_num_cpl_byte_rcvd;
545		*ptr++ = vpath_info->wrcrdtarb_xoff;
546		*ptr++ = vpath_info->rdcrdtarb_xoff;
547		*ptr++ = vpath_info->vpath_genstats_count0;
548		*ptr++ = vpath_info->vpath_genstats_count1;
549		*ptr++ = vpath_info->vpath_genstats_count2;
550		*ptr++ = vpath_info->vpath_genstats_count3;
551		*ptr++ = vpath_info->vpath_genstats_count4;
552		*ptr++ = vpath_info->vpath_genstats_count5;
553		*ptr++ = vpath_info->prog_event_vnum0;
554		*ptr++ = vpath_info->prog_event_vnum1;
555		*ptr++ = vpath_info->prog_event_vnum2;
556		*ptr++ = vpath_info->prog_event_vnum3;
557		*ptr++ = vpath_info->rx_multi_cast_frame_discard;
558		*ptr++ = vpath_info->rx_frm_transferred;
559		*ptr++ = vpath_info->rxd_returned;
560		*ptr++ = vpath_info->rx_mpa_len_fail_frms;
561		*ptr++ = vpath_info->rx_mpa_mrk_fail_frms;
562		*ptr++ = vpath_info->rx_mpa_crc_fail_frms;
563		*ptr++ = vpath_info->rx_permitted_frms;
564		*ptr++ = vpath_info->rx_vp_reset_discarded_frms;
565		*ptr++ = vpath_info->rx_wol_frms;
566		*ptr++ = vpath_info->tx_vp_reset_discarded_frms;
567	}
568
569	*ptr++ = 0;
570	*ptr++ = vdev->stats.vpaths_open;
571	*ptr++ = vdev->stats.vpath_open_fail;
572	*ptr++ = vdev->stats.link_up;
573	*ptr++ = vdev->stats.link_down;
574
575	for (k = 0; k < vdev->no_of_vpath; k++) {
576		*ptr += vdev->vpaths[k].fifo.stats.tx_frms;
577		*(ptr + 1) += vdev->vpaths[k].fifo.stats.tx_errors;
578		*(ptr + 2) += vdev->vpaths[k].fifo.stats.tx_bytes;
579		*(ptr + 3) += vdev->vpaths[k].fifo.stats.txd_not_free;
580		*(ptr + 4) += vdev->vpaths[k].fifo.stats.txd_out_of_desc;
581		*(ptr + 5) += vdev->vpaths[k].ring.stats.rx_frms;
582		*(ptr + 6) += vdev->vpaths[k].ring.stats.rx_errors;
583		*(ptr + 7) += vdev->vpaths[k].ring.stats.rx_bytes;
584		*(ptr + 8) += vdev->vpaths[k].ring.stats.rx_mcast;
585		*(ptr + 9) += vdev->vpaths[k].fifo.stats.pci_map_fail +
586				vdev->vpaths[k].ring.stats.pci_map_fail;
587		*(ptr + 10) += vdev->vpaths[k].ring.stats.skb_alloc_fail;
588	}
589
590	ptr += 12;
591
592	kfree(xmac_stats);
593	kfree(sw_stats);
594	kfree(hw_stats);
595}
596
597static void vxge_ethtool_get_strings(struct net_device *dev, u32 stringset,
598				     u8 *data)
599{
600	int stat_size = 0;
601	int i, j;
602	struct vxgedev *vdev = netdev_priv(dev);
603	switch (stringset) {
604	case ETH_SS_STATS:
605		vxge_add_string("VPATH STATISTICS%s\t\t\t",
606			&stat_size, data, "");
607		for (i = 0; i < vdev->no_of_vpath; i++) {
608			vxge_add_string("tx_ttl_eth_frms_%d\t\t\t",
609					&stat_size, data, i);
610			vxge_add_string("tx_ttl_eth_octects_%d\t\t",
611					&stat_size, data, i);
612			vxge_add_string("tx_data_octects_%d\t\t\t",
613					&stat_size, data, i);
614			vxge_add_string("tx_mcast_frms_%d\t\t\t",
615					&stat_size, data, i);
616			vxge_add_string("tx_bcast_frms_%d\t\t\t",
617					&stat_size, data, i);
618			vxge_add_string("tx_ucast_frms_%d\t\t\t",
619					&stat_size, data, i);
620			vxge_add_string("tx_tagged_frms_%d\t\t\t",
621					&stat_size, data, i);
622			vxge_add_string("tx_vld_ip_%d\t\t\t",
623					&stat_size, data, i);
624			vxge_add_string("tx_vld_ip_octects_%d\t\t",
625					&stat_size, data, i);
626			vxge_add_string("tx_icmp_%d\t\t\t\t",
627					&stat_size, data, i);
628			vxge_add_string("tx_tcp_%d\t\t\t\t",
629					&stat_size, data, i);
630			vxge_add_string("tx_rst_tcp_%d\t\t\t",
631					&stat_size, data, i);
632			vxge_add_string("tx_udp_%d\t\t\t\t",
633					&stat_size, data, i);
634			vxge_add_string("tx_unknown_proto_%d\t\t\t",
635					&stat_size, data, i);
636			vxge_add_string("tx_lost_ip_%d\t\t\t",
637					&stat_size, data, i);
638			vxge_add_string("tx_parse_error_%d\t\t\t",
639					&stat_size, data, i);
640			vxge_add_string("tx_tcp_offload_%d\t\t\t",
641					&stat_size, data, i);
642			vxge_add_string("tx_retx_tcp_offload_%d\t\t",
643					&stat_size, data, i);
644			vxge_add_string("tx_lost_ip_offload_%d\t\t",
645					&stat_size, data, i);
646			vxge_add_string("rx_ttl_eth_frms_%d\t\t\t",
647					&stat_size, data, i);
648			vxge_add_string("rx_vld_frms_%d\t\t\t",
649					&stat_size, data, i);
650			vxge_add_string("rx_offload_frms_%d\t\t\t",
651					&stat_size, data, i);
652			vxge_add_string("rx_ttl_eth_octects_%d\t\t",
653					&stat_size, data, i);
654			vxge_add_string("rx_data_octects_%d\t\t\t",
655					&stat_size, data, i);
656			vxge_add_string("rx_offload_octects_%d\t\t",
657					&stat_size, data, i);
658			vxge_add_string("rx_vld_mcast_frms_%d\t\t",
659					&stat_size, data, i);
660			vxge_add_string("rx_vld_bcast_frms_%d\t\t",
661					&stat_size, data, i);
662			vxge_add_string("rx_accepted_ucast_frms_%d\t\t",
663					&stat_size, data, i);
664			vxge_add_string("rx_accepted_nucast_frms_%d\t\t",
665					&stat_size, data, i);
666			vxge_add_string("rx_tagged_frms_%d\t\t\t",
667					&stat_size, data, i);
668			vxge_add_string("rx_long_frms_%d\t\t\t",
669					&stat_size, data, i);
670			vxge_add_string("rx_usized_frms_%d\t\t\t",
671					&stat_size, data, i);
672			vxge_add_string("rx_osized_frms_%d\t\t\t",
673					&stat_size, data, i);
674			vxge_add_string("rx_frag_frms_%d\t\t\t",
675					&stat_size, data, i);
676			vxge_add_string("rx_jabber_frms_%d\t\t\t",
677					&stat_size, data, i);
678			vxge_add_string("rx_ttl_64_frms_%d\t\t\t",
679					&stat_size, data, i);
680			vxge_add_string("rx_ttl_65_127_frms_%d\t\t",
681					&stat_size, data, i);
682			vxge_add_string("rx_ttl_128_255_frms_%d\t\t",
683					&stat_size, data, i);
684			vxge_add_string("rx_ttl_256_511_frms_%d\t\t",
685					&stat_size, data, i);
686			vxge_add_string("rx_ttl_512_1023_frms_%d\t\t",
687					&stat_size, data, i);
688			vxge_add_string("rx_ttl_1024_1518_frms_%d\t\t",
689					&stat_size, data, i);
690			vxge_add_string("rx_ttl_1519_4095_frms_%d\t\t",
691					&stat_size, data, i);
692			vxge_add_string("rx_ttl_4096_8191_frms_%d\t\t",
693					&stat_size, data, i);
694			vxge_add_string("rx_ttl_8192_max_frms_%d\t\t",
695					&stat_size, data, i);
696			vxge_add_string("rx_ttl_gt_max_frms_%d\t\t",
697					&stat_size, data, i);
698			vxge_add_string("rx_ip%d\t\t\t\t",
699					&stat_size, data, i);
700			vxge_add_string("rx_accepted_ip_%d\t\t\t",
701					&stat_size, data, i);
702			vxge_add_string("rx_ip_octects_%d\t\t\t",
703					&stat_size, data, i);
704			vxge_add_string("rx_err_ip_%d\t\t\t",
705					&stat_size, data, i);
706			vxge_add_string("rx_icmp_%d\t\t\t\t",
707					&stat_size, data, i);
708			vxge_add_string("rx_tcp_%d\t\t\t\t",
709					&stat_size, data, i);
710			vxge_add_string("rx_udp_%d\t\t\t\t",
711					&stat_size, data, i);
712			vxge_add_string("rx_err_tcp_%d\t\t\t",
713					&stat_size, data, i);
714			vxge_add_string("rx_lost_frms_%d\t\t\t",
715					&stat_size, data, i);
716			vxge_add_string("rx_lost_ip_%d\t\t\t",
717					&stat_size, data, i);
718			vxge_add_string("rx_lost_ip_offload_%d\t\t",
719					&stat_size, data, i);
720			vxge_add_string("rx_various_discard_%d\t\t",
721					&stat_size, data, i);
722			vxge_add_string("rx_sleep_discard_%d\t\t\t",
723					&stat_size, data, i);
724			vxge_add_string("rx_red_discard_%d\t\t\t",
725					&stat_size, data, i);
726			vxge_add_string("rx_queue_full_discard_%d\t\t",
727					&stat_size, data, i);
728			vxge_add_string("rx_mpa_ok_frms_%d\t\t\t",
729					&stat_size, data, i);
730		}
731
732		vxge_add_string("\nAGGR STATISTICS%s\t\t\t\t",
733			&stat_size, data, "");
734		for (i = 0; i < vdev->max_config_port; i++) {
735			vxge_add_string("tx_frms_%d\t\t\t\t",
736				&stat_size, data, i);
737			vxge_add_string("tx_data_octects_%d\t\t\t",
738				&stat_size, data, i);
739			vxge_add_string("tx_mcast_frms_%d\t\t\t",
740				&stat_size, data, i);
741			vxge_add_string("tx_bcast_frms_%d\t\t\t",
742				&stat_size, data, i);
743			vxge_add_string("tx_discarded_frms_%d\t\t",
744				&stat_size, data, i);
745			vxge_add_string("tx_errored_frms_%d\t\t\t",
746				&stat_size, data, i);
747			vxge_add_string("rx_frms_%d\t\t\t\t",
748				&stat_size, data, i);
749			vxge_add_string("rx_data_octects_%d\t\t\t",
750				&stat_size, data, i);
751			vxge_add_string("rx_mcast_frms_%d\t\t\t",
752				&stat_size, data, i);
753			vxge_add_string("rx_bcast_frms_%d\t\t\t",
754				&stat_size, data, i);
755			vxge_add_string("rx_discarded_frms_%d\t\t",
756				&stat_size, data, i);
757			vxge_add_string("rx_errored_frms_%d\t\t\t",
758				&stat_size, data, i);
759			vxge_add_string("rx_unknown_slow_proto_frms_%d\t",
760				&stat_size, data, i);
761		}
762
763		vxge_add_string("\nPORT STATISTICS%s\t\t\t\t",
764			&stat_size, data, "");
765		for (i = 0; i < vdev->max_config_port; i++) {
766			vxge_add_string("tx_ttl_frms_%d\t\t\t",
767				&stat_size, data, i);
768			vxge_add_string("tx_ttl_octects_%d\t\t\t",
769				&stat_size, data, i);
770			vxge_add_string("tx_data_octects_%d\t\t\t",
771				&stat_size, data, i);
772			vxge_add_string("tx_mcast_frms_%d\t\t\t",
773				&stat_size, data, i);
774			vxge_add_string("tx_bcast_frms_%d\t\t\t",
775				&stat_size, data, i);
776			vxge_add_string("tx_ucast_frms_%d\t\t\t",
777				&stat_size, data, i);
778			vxge_add_string("tx_tagged_frms_%d\t\t\t",
779				&stat_size, data, i);
780			vxge_add_string("tx_vld_ip_%d\t\t\t",
781				&stat_size, data, i);
782			vxge_add_string("tx_vld_ip_octects_%d\t\t",
783				&stat_size, data, i);
784			vxge_add_string("tx_icmp_%d\t\t\t\t",
785				&stat_size, data, i);
786			vxge_add_string("tx_tcp_%d\t\t\t\t",
787				&stat_size, data, i);
788			vxge_add_string("tx_rst_tcp_%d\t\t\t",
789				&stat_size, data, i);
790			vxge_add_string("tx_udp_%d\t\t\t\t",
791				&stat_size, data, i);
792			vxge_add_string("tx_parse_error_%d\t\t\t",
793				&stat_size, data, i);
794			vxge_add_string("tx_unknown_protocol_%d\t\t",
795				&stat_size, data, i);
796			vxge_add_string("tx_pause_ctrl_frms_%d\t\t",
797				&stat_size, data, i);
798			vxge_add_string("tx_marker_pdu_frms_%d\t\t",
799				&stat_size, data, i);
800			vxge_add_string("tx_lacpdu_frms_%d\t\t\t",
801				&stat_size, data, i);
802			vxge_add_string("tx_drop_ip_%d\t\t\t",
803				&stat_size, data, i);
804			vxge_add_string("tx_marker_resp_pdu_frms_%d\t\t",
805				&stat_size, data, i);
806			vxge_add_string("tx_xgmii_char2_match_%d\t\t",
807				&stat_size, data, i);
808			vxge_add_string("tx_xgmii_char1_match_%d\t\t",
809				&stat_size, data, i);
810			vxge_add_string("tx_xgmii_column2_match_%d\t\t",
811				&stat_size, data, i);
812			vxge_add_string("tx_xgmii_column1_match_%d\t\t",
813				&stat_size, data, i);
814			vxge_add_string("tx_any_err_frms_%d\t\t\t",
815				&stat_size, data, i);
816			vxge_add_string("tx_drop_frms_%d\t\t\t",
817				&stat_size, data, i);
818			vxge_add_string("rx_ttl_frms_%d\t\t\t",
819				&stat_size, data, i);
820			vxge_add_string("rx_vld_frms_%d\t\t\t",
821				&stat_size, data, i);
822			vxge_add_string("rx_offload_frms_%d\t\t\t",
823				&stat_size, data, i);
824			vxge_add_string("rx_ttl_octects_%d\t\t\t",
825				&stat_size, data, i);
826			vxge_add_string("rx_data_octects_%d\t\t\t",
827				&stat_size, data, i);
828			vxge_add_string("rx_offload_octects_%d\t\t",
829				&stat_size, data, i);
830			vxge_add_string("rx_vld_mcast_frms_%d\t\t",
831				&stat_size, data, i);
832			vxge_add_string("rx_vld_bcast_frms_%d\t\t",
833				&stat_size, data, i);
834			vxge_add_string("rx_accepted_ucast_frms_%d\t\t",
835				&stat_size, data, i);
836			vxge_add_string("rx_accepted_nucast_frms_%d\t\t",
837				&stat_size, data, i);
838			vxge_add_string("rx_tagged_frms_%d\t\t\t",
839				&stat_size, data, i);
840			vxge_add_string("rx_long_frms_%d\t\t\t",
841				&stat_size, data, i);
842			vxge_add_string("rx_usized_frms_%d\t\t\t",
843				&stat_size, data, i);
844			vxge_add_string("rx_osized_frms_%d\t\t\t",
845				&stat_size, data, i);
846			vxge_add_string("rx_frag_frms_%d\t\t\t",
847				&stat_size, data, i);
848			vxge_add_string("rx_jabber_frms_%d\t\t\t",
849				&stat_size, data, i);
850			vxge_add_string("rx_ttl_64_frms_%d\t\t\t",
851				&stat_size, data, i);
852			vxge_add_string("rx_ttl_65_127_frms_%d\t\t",
853				&stat_size, data, i);
854			vxge_add_string("rx_ttl_128_255_frms_%d\t\t",
855				&stat_size, data, i);
856			vxge_add_string("rx_ttl_256_511_frms_%d\t\t",
857				&stat_size, data, i);
858			vxge_add_string("rx_ttl_512_1023_frms_%d\t\t",
859				&stat_size, data, i);
860			vxge_add_string("rx_ttl_1024_1518_frms_%d\t\t",
861				&stat_size, data, i);
862			vxge_add_string("rx_ttl_1519_4095_frms_%d\t\t",
863				&stat_size, data, i);
864			vxge_add_string("rx_ttl_4096_8191_frms_%d\t\t",
865				&stat_size, data, i);
866			vxge_add_string("rx_ttl_8192_max_frms_%d\t\t",
867				&stat_size, data, i);
868			vxge_add_string("rx_ttl_gt_max_frms_%d\t\t",
869				&stat_size, data, i);
870			vxge_add_string("rx_ip_%d\t\t\t\t",
871				&stat_size, data, i);
872			vxge_add_string("rx_accepted_ip_%d\t\t\t",
873				&stat_size, data, i);
874			vxge_add_string("rx_ip_octets_%d\t\t\t",
875				&stat_size, data, i);
876			vxge_add_string("rx_err_ip_%d\t\t\t",
877				&stat_size, data, i);
878			vxge_add_string("rx_icmp_%d\t\t\t\t",
879				&stat_size, data, i);
880			vxge_add_string("rx_tcp_%d\t\t\t\t",
881				&stat_size, data, i);
882			vxge_add_string("rx_udp_%d\t\t\t\t",
883				&stat_size, data, i);
884			vxge_add_string("rx_err_tcp_%d\t\t\t",
885				&stat_size, data, i);
886			vxge_add_string("rx_pause_count_%d\t\t\t",
887				&stat_size, data, i);
888			vxge_add_string("rx_pause_ctrl_frms_%d\t\t",
889				&stat_size, data, i);
890			vxge_add_string("rx_unsup_ctrl_frms_%d\t\t",
891				&stat_size, data, i);
892			vxge_add_string("rx_fcs_err_frms_%d\t\t\t",
893				&stat_size, data, i);
894			vxge_add_string("rx_in_rng_len_err_frms_%d\t\t",
895				&stat_size, data, i);
896			vxge_add_string("rx_out_rng_len_err_frms_%d\t\t",
897				&stat_size, data, i);
898			vxge_add_string("rx_drop_frms_%d\t\t\t",
899				&stat_size, data, i);
900			vxge_add_string("rx_discard_frms_%d\t\t\t",
901				&stat_size, data, i);
902			vxge_add_string("rx_drop_ip_%d\t\t\t",
903				&stat_size, data, i);
904			vxge_add_string("rx_drop_udp_%d\t\t\t",
905				&stat_size, data, i);
906			vxge_add_string("rx_marker_pdu_frms_%d\t\t",
907				&stat_size, data, i);
908			vxge_add_string("rx_lacpdu_frms_%d\t\t\t",
909				&stat_size, data, i);
910			vxge_add_string("rx_unknown_pdu_frms_%d\t\t",
911				&stat_size, data, i);
912			vxge_add_string("rx_marker_resp_pdu_frms_%d\t\t",
913				&stat_size, data, i);
914			vxge_add_string("rx_fcs_discard_%d\t\t\t",
915				&stat_size, data, i);
916			vxge_add_string("rx_illegal_pdu_frms_%d\t\t",
917				&stat_size, data, i);
918			vxge_add_string("rx_switch_discard_%d\t\t",
919				&stat_size, data, i);
920			vxge_add_string("rx_len_discard_%d\t\t\t",
921				&stat_size, data, i);
922			vxge_add_string("rx_rpa_discard_%d\t\t\t",
923				&stat_size, data, i);
924			vxge_add_string("rx_l2_mgmt_discard_%d\t\t",
925				&stat_size, data, i);
926			vxge_add_string("rx_rts_discard_%d\t\t\t",
927				&stat_size, data, i);
928			vxge_add_string("rx_trash_discard_%d\t\t\t",
929				&stat_size, data, i);
930			vxge_add_string("rx_buff_full_discard_%d\t\t",
931				&stat_size, data, i);
932			vxge_add_string("rx_red_discard_%d\t\t\t",
933				&stat_size, data, i);
934			vxge_add_string("rx_xgmii_ctrl_err_cnt_%d\t\t",
935				&stat_size, data, i);
936			vxge_add_string("rx_xgmii_data_err_cnt_%d\t\t",
937				&stat_size, data, i);
938			vxge_add_string("rx_xgmii_char1_match_%d\t\t",
939				&stat_size, data, i);
940			vxge_add_string("rx_xgmii_err_sym_%d\t\t\t",
941				&stat_size, data, i);
942			vxge_add_string("rx_xgmii_column1_match_%d\t\t",
943				&stat_size, data, i);
944			vxge_add_string("rx_xgmii_char2_match_%d\t\t",
945				&stat_size, data, i);
946			vxge_add_string("rx_local_fault_%d\t\t\t",
947				&stat_size, data, i);
948			vxge_add_string("rx_xgmii_column2_match_%d\t\t",
949				&stat_size, data, i);
950			vxge_add_string("rx_jettison_%d\t\t\t",
951				&stat_size, data, i);
952			vxge_add_string("rx_remote_fault_%d\t\t\t",
953				&stat_size, data, i);
954		}
955
956		vxge_add_string("\n SOFTWARE STATISTICS%s\t\t\t",
957			&stat_size, data, "");
958		for (i = 0; i < vdev->no_of_vpath; i++) {
959			vxge_add_string("soft_reset_cnt_%d\t\t\t",
960				&stat_size, data, i);
961			vxge_add_string("unknown_alarms_%d\t\t\t",
962				&stat_size, data, i);
963			vxge_add_string("network_sustained_fault_%d\t\t",
964				&stat_size, data, i);
965			vxge_add_string("network_sustained_ok_%d\t\t",
966				&stat_size, data, i);
967			vxge_add_string("kdfcctl_fifo0_overwrite_%d\t\t",
968				&stat_size, data, i);
969			vxge_add_string("kdfcctl_fifo0_poison_%d\t\t",
970				&stat_size, data, i);
971			vxge_add_string("kdfcctl_fifo0_dma_error_%d\t\t",
972				&stat_size, data, i);
973			vxge_add_string("dblgen_fifo0_overflow_%d\t\t",
974				&stat_size, data, i);
975			vxge_add_string("statsb_pif_chain_error_%d\t\t",
976				&stat_size, data, i);
977			vxge_add_string("statsb_drop_timeout_%d\t\t",
978				&stat_size, data, i);
979			vxge_add_string("target_illegal_access_%d\t\t",
980				&stat_size, data, i);
981			vxge_add_string("ini_serr_det_%d\t\t\t",
982				&stat_size, data, i);
983			vxge_add_string("prc_ring_bumps_%d\t\t\t",
984				&stat_size, data, i);
985			vxge_add_string("prc_rxdcm_sc_err_%d\t\t\t",
986				&stat_size, data, i);
987			vxge_add_string("prc_rxdcm_sc_abort_%d\t\t",
988				&stat_size, data, i);
989			vxge_add_string("prc_quanta_size_err_%d\t\t",
990				&stat_size, data, i);
991			vxge_add_string("ring_full_cnt_%d\t\t\t",
992				&stat_size, data, i);
993			vxge_add_string("ring_usage_cnt_%d\t\t\t",
994				&stat_size, data, i);
995			vxge_add_string("ring_usage_max_%d\t\t\t",
996				&stat_size, data, i);
997			vxge_add_string("ring_reserve_free_swaps_cnt_%d\t",
998				&stat_size, data, i);
999			vxge_add_string("ring_total_compl_cnt_%d\t\t",
1000				&stat_size, data, i);
1001			for (j = 0; j < VXGE_HW_DTR_MAX_T_CODE; j++)
1002				vxge_add_string("rxd_t_code_err_cnt%d_%d\t\t",
1003					&stat_size, data, j, i);
1004			vxge_add_string("fifo_full_cnt_%d\t\t\t",
1005				&stat_size, data, i);
1006			vxge_add_string("fifo_usage_cnt_%d\t\t\t",
1007				&stat_size, data, i);
1008			vxge_add_string("fifo_usage_max_%d\t\t\t",
1009				&stat_size, data, i);
1010			vxge_add_string("fifo_reserve_free_swaps_cnt_%d\t",
1011				&stat_size, data, i);
1012			vxge_add_string("fifo_total_compl_cnt_%d\t\t",
1013				&stat_size, data, i);
1014			vxge_add_string("fifo_total_posts_%d\t\t\t",
1015				&stat_size, data, i);
1016			vxge_add_string("fifo_total_buffers_%d\t\t",
1017				&stat_size, data, i);
1018			for (j = 0; j < VXGE_HW_DTR_MAX_T_CODE; j++)
1019				vxge_add_string("txd_t_code_err_cnt%d_%d\t\t",
1020					&stat_size, data, j, i);
1021		}
1022
1023		vxge_add_string("\n HARDWARE STATISTICS%s\t\t\t",
1024				&stat_size, data, "");
1025		for (i = 0; i < vdev->no_of_vpath; i++) {
1026			vxge_add_string("ini_num_mwr_sent_%d\t\t\t",
1027					&stat_size, data, i);
1028			vxge_add_string("ini_num_mrd_sent_%d\t\t\t",
1029					&stat_size, data, i);
1030			vxge_add_string("ini_num_cpl_rcvd_%d\t\t\t",
1031					&stat_size, data, i);
1032			vxge_add_string("ini_num_mwr_byte_sent_%d\t\t",
1033					&stat_size, data, i);
1034			vxge_add_string("ini_num_cpl_byte_rcvd_%d\t\t",
1035					&stat_size, data, i);
1036			vxge_add_string("wrcrdtarb_xoff_%d\t\t\t",
1037					&stat_size, data, i);
1038			vxge_add_string("rdcrdtarb_xoff_%d\t\t\t",
1039					&stat_size, data, i);
1040			vxge_add_string("vpath_genstats_count0_%d\t\t",
1041					&stat_size, data, i);
1042			vxge_add_string("vpath_genstats_count1_%d\t\t",
1043					&stat_size, data, i);
1044			vxge_add_string("vpath_genstats_count2_%d\t\t",
1045					&stat_size, data, i);
1046			vxge_add_string("vpath_genstats_count3_%d\t\t",
1047					&stat_size, data, i);
1048			vxge_add_string("vpath_genstats_count4_%d\t\t",
1049					&stat_size, data, i);
1050			vxge_add_string("vpath_genstats_count5_%d\t\t",
1051					&stat_size, data, i);
1052			vxge_add_string("prog_event_vnum0_%d\t\t\t",
1053					&stat_size, data, i);
1054			vxge_add_string("prog_event_vnum1_%d\t\t\t",
1055					&stat_size, data, i);
1056			vxge_add_string("prog_event_vnum2_%d\t\t\t",
1057					&stat_size, data, i);
1058			vxge_add_string("prog_event_vnum3_%d\t\t\t",
1059					&stat_size, data, i);
1060			vxge_add_string("rx_multi_cast_frame_discard_%d\t",
1061					&stat_size, data, i);
1062			vxge_add_string("rx_frm_transferred_%d\t\t",
1063					&stat_size, data, i);
1064			vxge_add_string("rxd_returned_%d\t\t\t",
1065					&stat_size, data, i);
1066			vxge_add_string("rx_mpa_len_fail_frms_%d\t\t",
1067					&stat_size, data, i);
1068			vxge_add_string("rx_mpa_mrk_fail_frms_%d\t\t",
1069					&stat_size, data, i);
1070			vxge_add_string("rx_mpa_crc_fail_frms_%d\t\t",
1071					&stat_size, data, i);
1072			vxge_add_string("rx_permitted_frms_%d\t\t",
1073					&stat_size, data, i);
1074			vxge_add_string("rx_vp_reset_discarded_frms_%d\t",
1075					&stat_size, data, i);
1076			vxge_add_string("rx_wol_frms_%d\t\t\t",
1077					&stat_size, data, i);
1078			vxge_add_string("tx_vp_reset_discarded_frms_%d\t",
1079					&stat_size, data, i);
1080		}
1081
1082		memcpy(data + stat_size, &ethtool_driver_stats_keys,
1083			sizeof(ethtool_driver_stats_keys));
1084	}
1085}
1086
1087static int vxge_ethtool_get_regs_len(struct net_device *dev)
1088{
1089	struct vxgedev *vdev = netdev_priv(dev);
1090
1091	return sizeof(struct vxge_hw_vpath_reg) * vdev->no_of_vpath;
1092}
1093
1094static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset)
1095{
1096	struct vxgedev *vdev = netdev_priv(dev);
1097
1098	switch (sset) {
1099	case ETH_SS_STATS:
1100		return VXGE_TITLE_LEN +
1101			(vdev->no_of_vpath * VXGE_HW_VPATH_STATS_LEN) +
1102			(vdev->max_config_port * VXGE_HW_AGGR_STATS_LEN) +
1103			(vdev->max_config_port * VXGE_HW_PORT_STATS_LEN) +
1104			(vdev->no_of_vpath * VXGE_HW_VPATH_TX_STATS_LEN) +
1105			(vdev->no_of_vpath * VXGE_HW_VPATH_RX_STATS_LEN) +
1106			(vdev->no_of_vpath * VXGE_SW_STATS_LEN) +
1107			DRIVER_STAT_LEN;
1108	default:
1109		return -EOPNOTSUPP;
1110	}
1111}
1112
1113static int vxge_fw_flash(struct net_device *dev, struct ethtool_flash *parms)
1114{
1115	struct vxgedev *vdev = netdev_priv(dev);
1116
1117	if (vdev->max_vpath_supported != VXGE_HW_MAX_VIRTUAL_PATHS) {
1118		printk(KERN_INFO "Single Function Mode is required to flash the"
1119		       " firmware\n");
1120		return -EINVAL;
1121	}
1122
1123	if (netif_running(dev)) {
1124		printk(KERN_INFO "Interface %s must be down to flash the "
1125		       "firmware\n", dev->name);
1126		return -EBUSY;
1127	}
1128
1129	return vxge_fw_upgrade(vdev, parms->data, 1);
1130}
1131
1132static const struct ethtool_ops vxge_ethtool_ops = {
1133	.get_settings		= vxge_ethtool_gset,
1134	.set_settings		= vxge_ethtool_sset,
1135	.get_drvinfo		= vxge_ethtool_gdrvinfo,
1136	.get_regs_len		= vxge_ethtool_get_regs_len,
1137	.get_regs		= vxge_ethtool_gregs,
1138	.get_link		= ethtool_op_get_link,
1139	.get_pauseparam		= vxge_ethtool_getpause_data,
1140	.set_pauseparam		= vxge_ethtool_setpause_data,
1141	.get_strings		= vxge_ethtool_get_strings,
1142	.set_phys_id		= vxge_ethtool_idnic,
1143	.get_sset_count		= vxge_ethtool_get_sset_count,
1144	.get_ethtool_stats	= vxge_get_ethtool_stats,
1145	.flash_device		= vxge_fw_flash,
1146};
1147
1148void vxge_initialize_ethtool_ops(struct net_device *ndev)
1149{
1150	ndev->ethtool_ops = &vxge_ethtool_ops;
1151}
1152