1004b26b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2aa43c215SJeff Kirsher /*
3aa43c215SJeff Kirsher  * QLogic qlcnic NIC Driver
4577ae39dSJitendra Kalsaria  * Copyright (c) 2009-2013 QLogic Corporation
5aa43c215SJeff Kirsher  */
6aa43c215SJeff Kirsher 
7aa43c215SJeff Kirsher #include <linux/types.h>
8aa43c215SJeff Kirsher #include <linux/delay.h>
9aa43c215SJeff Kirsher #include <linux/pci.h>
10aa43c215SJeff Kirsher #include <linux/io.h>
11aa43c215SJeff Kirsher #include <linux/netdevice.h>
12aa43c215SJeff Kirsher #include <linux/ethtool.h>
13aa43c215SJeff Kirsher 
14aa43c215SJeff Kirsher #include "qlcnic.h"
15aa43c215SJeff Kirsher 
16aa43c215SJeff Kirsher struct qlcnic_stats {
17aa43c215SJeff Kirsher 	char stat_string[ETH_GSTRING_LEN];
18aa43c215SJeff Kirsher 	int sizeof_stat;
19aa43c215SJeff Kirsher 	int stat_offset;
20aa43c215SJeff Kirsher };
21aa43c215SJeff Kirsher 
22c593642cSPankaj Bharadiya #define QLC_SIZEOF(m) sizeof_field(struct qlcnic_adapter, m)
23aa43c215SJeff Kirsher #define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
247e38d04bSSony Chacko static const u32 qlcnic_fw_dump_level[] = {
257e38d04bSSony Chacko 	0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
267e38d04bSSony Chacko };
27aa43c215SJeff Kirsher 
28aa43c215SJeff Kirsher static const struct qlcnic_stats qlcnic_gstrings_stats[] = {
29f27c75b3SHimanshu Madhani 	{"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)},
30f27c75b3SHimanshu Madhani 	{"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)},
317e38d04bSSony Chacko 	{"xmit_called", QLC_SIZEOF(stats.xmitcalled),
327e38d04bSSony Chacko 	 QLC_OFF(stats.xmitcalled)},
337e38d04bSSony Chacko 	{"xmit_finished", QLC_SIZEOF(stats.xmitfinished),
347e38d04bSSony Chacko 	 QLC_OFF(stats.xmitfinished)},
35aa43c215SJeff Kirsher 	{"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error),
36aa43c215SJeff Kirsher 	 QLC_OFF(stats.tx_dma_map_error)},
37f27c75b3SHimanshu Madhani 	{"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)},
38f27c75b3SHimanshu Madhani 	{"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)},
39f27c75b3SHimanshu Madhani 	{"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error),
40f27c75b3SHimanshu Madhani 	 QLC_OFF(stats.rx_dma_map_error)},
41f27c75b3SHimanshu Madhani 	{"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)},
42f27c75b3SHimanshu Madhani 	{"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)},
43f27c75b3SHimanshu Madhani 	{"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)},
44f27c75b3SHimanshu Madhani 	{"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)},
45f27c75b3SHimanshu Madhani 	{"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)},
46f27c75b3SHimanshu Madhani 	{"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)},
47f27c75b3SHimanshu Madhani 	{"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)},
48f27c75b3SHimanshu Madhani 	{"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)},
49381709deSShahed Shaikh 	{"encap_lso_frames", QLC_SIZEOF(stats.encap_lso_frames),
50381709deSShahed Shaikh 	 QLC_OFF(stats.encap_lso_frames)},
51381709deSShahed Shaikh 	{"encap_tx_csummed", QLC_SIZEOF(stats.encap_tx_csummed),
52381709deSShahed Shaikh 	 QLC_OFF(stats.encap_tx_csummed)},
532b3d7b75SShahed Shaikh 	{"encap_rx_csummed", QLC_SIZEOF(stats.encap_rx_csummed),
542b3d7b75SShahed Shaikh 	 QLC_OFF(stats.encap_rx_csummed)},
55f27c75b3SHimanshu Madhani 	{"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure),
56f27c75b3SHimanshu Madhani 	 QLC_OFF(stats.skb_alloc_failure)},
577e38d04bSSony Chacko 	{"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun),
587e38d04bSSony Chacko 	 QLC_OFF(stats.mac_filter_limit_overrun)},
597e38d04bSSony Chacko 	{"spurious intr", QLC_SIZEOF(stats.spurious_intr),
607e38d04bSSony Chacko 	 QLC_OFF(stats.spurious_intr)},
61819bfe76SRajesh Borundia 	{"mbx spurious intr", QLC_SIZEOF(stats.mbx_spurious_intr),
62819bfe76SRajesh Borundia 	 QLC_OFF(stats.mbx_spurious_intr)},
63aa43c215SJeff Kirsher };
64aa43c215SJeff Kirsher 
65aa43c215SJeff Kirsher static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = {
66aa43c215SJeff Kirsher 	"tx unicast frames",
67aa43c215SJeff Kirsher 	"tx multicast frames",
68aa43c215SJeff Kirsher 	"tx broadcast frames",
69aa43c215SJeff Kirsher 	"tx dropped frames",
70aa43c215SJeff Kirsher 	"tx errors",
71aa43c215SJeff Kirsher 	"tx local frames",
72aa43c215SJeff Kirsher 	"tx numbytes",
73f27c75b3SHimanshu Madhani 	"rx unicast frames",
74f27c75b3SHimanshu Madhani 	"rx multicast frames",
75f27c75b3SHimanshu Madhani 	"rx broadcast frames",
76f27c75b3SHimanshu Madhani 	"rx dropped frames",
77f27c75b3SHimanshu Madhani 	"rx errors",
78f27c75b3SHimanshu Madhani 	"rx local frames",
79f27c75b3SHimanshu Madhani 	"rx numbytes",
80aa43c215SJeff Kirsher };
81aa43c215SJeff Kirsher 
827e38d04bSSony Chacko static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = {
837e38d04bSSony Chacko 	"ctx_tx_bytes",
847e38d04bSSony Chacko 	"ctx_tx_pkts",
857e38d04bSSony Chacko 	"ctx_tx_errors",
867e38d04bSSony Chacko 	"ctx_tx_dropped_pkts",
877e38d04bSSony Chacko 	"ctx_tx_num_buffers",
887e38d04bSSony Chacko };
897e38d04bSSony Chacko 
907e38d04bSSony Chacko static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = {
9154a8997cSJitendra Kalsaria 	"mac_tx_frames",
9254a8997cSJitendra Kalsaria 	"mac_tx_bytes",
9354a8997cSJitendra Kalsaria 	"mac_tx_mcast_pkts",
9454a8997cSJitendra Kalsaria 	"mac_tx_bcast_pkts",
9554a8997cSJitendra Kalsaria 	"mac_tx_pause_cnt",
9654a8997cSJitendra Kalsaria 	"mac_tx_ctrl_pkt",
9754a8997cSJitendra Kalsaria 	"mac_tx_lt_64b_pkts",
9854a8997cSJitendra Kalsaria 	"mac_tx_lt_127b_pkts",
9954a8997cSJitendra Kalsaria 	"mac_tx_lt_255b_pkts",
10054a8997cSJitendra Kalsaria 	"mac_tx_lt_511b_pkts",
10154a8997cSJitendra Kalsaria 	"mac_tx_lt_1023b_pkts",
10254a8997cSJitendra Kalsaria 	"mac_tx_lt_1518b_pkts",
10354a8997cSJitendra Kalsaria 	"mac_tx_gt_1518b_pkts",
10454a8997cSJitendra Kalsaria 	"mac_rx_frames",
10554a8997cSJitendra Kalsaria 	"mac_rx_bytes",
10654a8997cSJitendra Kalsaria 	"mac_rx_mcast_pkts",
10754a8997cSJitendra Kalsaria 	"mac_rx_bcast_pkts",
10854a8997cSJitendra Kalsaria 	"mac_rx_pause_cnt",
10954a8997cSJitendra Kalsaria 	"mac_rx_ctrl_pkt",
11054a8997cSJitendra Kalsaria 	"mac_rx_lt_64b_pkts",
11154a8997cSJitendra Kalsaria 	"mac_rx_lt_127b_pkts",
11254a8997cSJitendra Kalsaria 	"mac_rx_lt_255b_pkts",
11354a8997cSJitendra Kalsaria 	"mac_rx_lt_511b_pkts",
11454a8997cSJitendra Kalsaria 	"mac_rx_lt_1023b_pkts",
11554a8997cSJitendra Kalsaria 	"mac_rx_lt_1518b_pkts",
11654a8997cSJitendra Kalsaria 	"mac_rx_gt_1518b_pkts",
11754a8997cSJitendra Kalsaria 	"mac_rx_length_error",
11854a8997cSJitendra Kalsaria 	"mac_rx_length_small",
11954a8997cSJitendra Kalsaria 	"mac_rx_length_large",
12054a8997cSJitendra Kalsaria 	"mac_rx_jabber",
12154a8997cSJitendra Kalsaria 	"mac_rx_dropped",
1227e38d04bSSony Chacko 	"mac_crc_error",
12354a8997cSJitendra Kalsaria 	"mac_align_error",
12452290740SShahed Shaikh 	"eswitch_frames",
12552290740SShahed Shaikh 	"eswitch_bytes",
12652290740SShahed Shaikh 	"eswitch_multicast_frames",
12752290740SShahed Shaikh 	"eswitch_broadcast_frames",
12852290740SShahed Shaikh 	"eswitch_unicast_frames",
12952290740SShahed Shaikh 	"eswitch_error_free_frames",
13052290740SShahed Shaikh 	"eswitch_error_free_bytes",
13154a8997cSJitendra Kalsaria };
13254a8997cSJitendra Kalsaria 
133aa43c215SJeff Kirsher #define QLCNIC_STATS_LEN	ARRAY_SIZE(qlcnic_gstrings_stats)
134aa4a1f7dSHimanshu Madhani 
135f27c75b3SHimanshu Madhani static const char qlcnic_tx_queue_stats_strings[][ETH_GSTRING_LEN] = {
136aa4a1f7dSHimanshu Madhani 	"xmit_on",
137aa4a1f7dSHimanshu Madhani 	"xmit_off",
138aa4a1f7dSHimanshu Madhani 	"xmit_called",
139aa4a1f7dSHimanshu Madhani 	"xmit_finished",
140f27c75b3SHimanshu Madhani 	"tx_bytes",
141aa4a1f7dSHimanshu Madhani };
142aa4a1f7dSHimanshu Madhani 
143f27c75b3SHimanshu Madhani #define QLCNIC_TX_STATS_LEN	ARRAY_SIZE(qlcnic_tx_queue_stats_strings)
144f27c75b3SHimanshu Madhani 
1457e38d04bSSony Chacko static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = {
1467e38d04bSSony Chacko 	"ctx_rx_bytes",
1477e38d04bSSony Chacko 	"ctx_rx_pkts",
1487e38d04bSSony Chacko 	"ctx_lro_pkt_cnt",
1497e38d04bSSony Chacko 	"ctx_ip_csum_error",
1507e38d04bSSony Chacko 	"ctx_rx_pkts_wo_ctx",
1518c046410SShahed Shaikh 	"ctx_rx_pkts_drop_wo_sds_on_card",
1528c046410SShahed Shaikh 	"ctx_rx_pkts_drop_wo_sds_on_host",
1537e38d04bSSony Chacko 	"ctx_rx_osized_pkts",
1547e38d04bSSony Chacko 	"ctx_rx_pkts_dropped_wo_rds",
1557e38d04bSSony Chacko 	"ctx_rx_unexpected_mcast_pkts",
1567e38d04bSSony Chacko 	"ctx_invalid_mac_address",
1578c046410SShahed Shaikh 	"ctx_rx_rds_ring_prim_attempted",
1587e38d04bSSony Chacko 	"ctx_rx_rds_ring_prim_success",
1597e38d04bSSony Chacko 	"ctx_num_lro_flows_added",
1607e38d04bSSony Chacko 	"ctx_num_lro_flows_removed",
1617e38d04bSSony Chacko 	"ctx_num_lro_flows_active",
1627e38d04bSSony Chacko 	"ctx_pkts_dropped_unknown",
1637e38d04bSSony Chacko };
164aa43c215SJeff Kirsher 
165aa43c215SJeff Kirsher static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = {
166aa43c215SJeff Kirsher 	"Register_Test_on_offline",
167aa43c215SJeff Kirsher 	"Link_Test_on_offline",
168aa43c215SJeff Kirsher 	"Interrupt_Test_offline",
169aa43c215SJeff Kirsher 	"Internal_Loopback_offline",
1702e3ea7e7SShahed Shaikh 	"External_Loopback_offline",
1717e38d04bSSony Chacko 	"EEPROM_Test_offline"
172aa43c215SJeff Kirsher };
173aa43c215SJeff Kirsher 
174aa43c215SJeff Kirsher #define QLCNIC_TEST_LEN	ARRAY_SIZE(qlcnic_gstrings_test)
175aa43c215SJeff Kirsher 
qlcnic_82xx_statistics(struct qlcnic_adapter * adapter)176d6e9c89aSShahed Shaikh static inline int qlcnic_82xx_statistics(struct qlcnic_adapter *adapter)
1777e38d04bSSony Chacko {
178d6e9c89aSShahed Shaikh 	return ARRAY_SIZE(qlcnic_gstrings_stats) +
179d6e9c89aSShahed Shaikh 	       ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
180d6e9c89aSShahed Shaikh 	       QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
1817e38d04bSSony Chacko }
1827e38d04bSSony Chacko 
qlcnic_83xx_statistics(struct qlcnic_adapter * adapter)183d6e9c89aSShahed Shaikh static inline int qlcnic_83xx_statistics(struct qlcnic_adapter *adapter)
1847e38d04bSSony Chacko {
185d6e9c89aSShahed Shaikh 	return ARRAY_SIZE(qlcnic_gstrings_stats) +
186d6e9c89aSShahed Shaikh 	       ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) +
1877e38d04bSSony Chacko 	       ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) +
188d6e9c89aSShahed Shaikh 	       ARRAY_SIZE(qlcnic_83xx_rx_stats_strings) +
189d6e9c89aSShahed Shaikh 	       QLCNIC_TX_STATS_LEN * adapter->drv_tx_rings;
1907e38d04bSSony Chacko }
1917e38d04bSSony Chacko 
qlcnic_dev_statistics_len(struct qlcnic_adapter * adapter)1927e38d04bSSony Chacko static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter)
1937e38d04bSSony Chacko {
194d6e9c89aSShahed Shaikh 	int len = -1;
195d6e9c89aSShahed Shaikh 
196d6e9c89aSShahed Shaikh 	if (qlcnic_82xx_check(adapter)) {
197d6e9c89aSShahed Shaikh 		len = qlcnic_82xx_statistics(adapter);
198d6e9c89aSShahed Shaikh 		if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
199d6e9c89aSShahed Shaikh 			len += ARRAY_SIZE(qlcnic_device_gstrings_stats);
200d6e9c89aSShahed Shaikh 	} else if (qlcnic_83xx_check(adapter)) {
201d6e9c89aSShahed Shaikh 		len = qlcnic_83xx_statistics(adapter);
202d6e9c89aSShahed Shaikh 	}
203d6e9c89aSShahed Shaikh 
204d6e9c89aSShahed Shaikh 	return len;
2057e38d04bSSony Chacko }
2067e38d04bSSony Chacko 
207710a1a49SPratik Pujar #define	QLCNIC_TX_INTR_NOT_CONFIGURED	0X78563412
208710a1a49SPratik Pujar 
209aa43c215SJeff Kirsher #define QLCNIC_MAX_EEPROM_LEN   1024
210aa43c215SJeff Kirsher 
211aa43c215SJeff Kirsher static const u32 diag_registers[] = {
2122c6196d2SShahed Shaikh 	QLCNIC_CMDPEG_STATE,
2132c6196d2SShahed Shaikh 	QLCNIC_RCVPEG_STATE,
2142c6196d2SShahed Shaikh 	QLCNIC_FW_CAPABILITIES,
215aa43c215SJeff Kirsher 	QLCNIC_CRB_DRV_ACTIVE,
216aa43c215SJeff Kirsher 	QLCNIC_CRB_DEV_STATE,
217aa43c215SJeff Kirsher 	QLCNIC_CRB_DRV_STATE,
218aa43c215SJeff Kirsher 	QLCNIC_CRB_DRV_SCRATCH,
219aa43c215SJeff Kirsher 	QLCNIC_CRB_DEV_PARTITION_INFO,
220aa43c215SJeff Kirsher 	QLCNIC_CRB_DRV_IDC_VER,
221aa43c215SJeff Kirsher 	QLCNIC_PEG_ALIVE_COUNTER,
222aa43c215SJeff Kirsher 	QLCNIC_PEG_HALT_STATUS1,
223aa43c215SJeff Kirsher 	QLCNIC_PEG_HALT_STATUS2,
2247e38d04bSSony Chacko 	-1
2257e38d04bSSony Chacko };
2267e38d04bSSony Chacko 
2272c6196d2SShahed Shaikh 
2287e38d04bSSony Chacko static const u32 ext_diag_registers[] = {
2297e38d04bSSony Chacko 	CRB_XG_STATE_P3P,
2307e38d04bSSony Chacko 	ISR_INT_STATE_REG,
231aa43c215SJeff Kirsher 	QLCNIC_CRB_PEG_NET_0+0x3c,
232aa43c215SJeff Kirsher 	QLCNIC_CRB_PEG_NET_1+0x3c,
233aa43c215SJeff Kirsher 	QLCNIC_CRB_PEG_NET_2+0x3c,
234aa43c215SJeff Kirsher 	QLCNIC_CRB_PEG_NET_4+0x3c,
235aa43c215SJeff Kirsher 	-1
236aa43c215SJeff Kirsher };
237aa43c215SJeff Kirsher 
2382f514c52SJitendra Kalsaria #define QLCNIC_MGMT_API_VERSION	3
239710a1a49SPratik Pujar #define QLCNIC_ETHTOOL_REGS_VER	4
240710a1a49SPratik Pujar 
qlcnic_get_ring_regs_len(struct qlcnic_adapter * adapter)241710a1a49SPratik Pujar static inline int qlcnic_get_ring_regs_len(struct qlcnic_adapter *adapter)
242710a1a49SPratik Pujar {
24334e8c406SHimanshu Madhani 	int ring_regs_cnt = (adapter->drv_tx_rings * 5) +
244710a1a49SPratik Pujar 			    (adapter->max_rds_rings * 2) +
24534e8c406SHimanshu Madhani 			    (adapter->drv_sds_rings * 3) + 5;
246710a1a49SPratik Pujar 	return ring_regs_cnt * sizeof(u32);
247710a1a49SPratik Pujar }
2487e38d04bSSony Chacko 
qlcnic_get_regs_len(struct net_device * dev)249aa43c215SJeff Kirsher static int qlcnic_get_regs_len(struct net_device *dev)
250aa43c215SJeff Kirsher {
2517e38d04bSSony Chacko 	struct qlcnic_adapter *adapter = netdev_priv(dev);
2527e38d04bSSony Chacko 	u32 len;
2537e38d04bSSony Chacko 
2547e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
2557e38d04bSSony Chacko 		len = qlcnic_83xx_get_regs_len(adapter);
2567e38d04bSSony Chacko 	else
2577e38d04bSSony Chacko 		len = sizeof(ext_diag_registers) + sizeof(diag_registers);
2587e38d04bSSony Chacko 
259710a1a49SPratik Pujar 	len += ((QLCNIC_DEV_INFO_SIZE + 2) * sizeof(u32));
260710a1a49SPratik Pujar 	len += qlcnic_get_ring_regs_len(adapter);
261710a1a49SPratik Pujar 	return len;
262aa43c215SJeff Kirsher }
263aa43c215SJeff Kirsher 
qlcnic_get_eeprom_len(struct net_device * dev)264aa43c215SJeff Kirsher static int qlcnic_get_eeprom_len(struct net_device *dev)
265aa43c215SJeff Kirsher {
266aa43c215SJeff Kirsher 	return QLCNIC_FLASH_TOTAL_SIZE;
267aa43c215SJeff Kirsher }
268aa43c215SJeff Kirsher 
269aa43c215SJeff Kirsher static void
qlcnic_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * drvinfo)270aa43c215SJeff Kirsher qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
271aa43c215SJeff Kirsher {
272aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
273aa43c215SJeff Kirsher 	u32 fw_major, fw_minor, fw_build;
2747e38d04bSSony Chacko 	fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR);
2757e38d04bSSony Chacko 	fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR);
2767e38d04bSSony Chacko 	fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB);
27768aad78cSRick Jones 	snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
27868aad78cSRick Jones 		"%d.%d.%d", fw_major, fw_minor, fw_build);
279aa43c215SJeff Kirsher 
280*f029c781SWolfram Sang 	strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
28168aad78cSRick Jones 		sizeof(drvinfo->bus_info));
282*f029c781SWolfram Sang 	strscpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
283*f029c781SWolfram Sang 	strscpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
28468aad78cSRick Jones 		sizeof(drvinfo->version));
285aa43c215SJeff Kirsher }
286aa43c215SJeff Kirsher 
qlcnic_82xx_get_link_ksettings(struct qlcnic_adapter * adapter,struct ethtool_link_ksettings * ecmd)28749cef10fSPhilippe Reynes static int qlcnic_82xx_get_link_ksettings(struct qlcnic_adapter *adapter,
28849cef10fSPhilippe Reynes 					  struct ethtool_link_ksettings *ecmd)
289b938662dSHimanshu Madhani {
2907e38d04bSSony Chacko 	struct qlcnic_hardware_context *ahw = adapter->ahw;
2917e38d04bSSony Chacko 	u32 speed, reg;
2924bd8e738SHimanshu Madhani 	int check_sfp_module = 0, err = 0;
2937e38d04bSSony Chacko 	u16 pcifn = ahw->pci_func;
29449cef10fSPhilippe Reynes 	u32 supported, advertising;
295aa43c215SJeff Kirsher 
296aa43c215SJeff Kirsher 	/* read which mode */
297aa43c215SJeff Kirsher 	if (adapter->ahw->port_type == QLCNIC_GBE) {
29849cef10fSPhilippe Reynes 		supported = (SUPPORTED_10baseT_Half |
299aa43c215SJeff Kirsher 				   SUPPORTED_10baseT_Full |
300aa43c215SJeff Kirsher 				   SUPPORTED_100baseT_Half |
301aa43c215SJeff Kirsher 				   SUPPORTED_100baseT_Full |
302aa43c215SJeff Kirsher 				   SUPPORTED_1000baseT_Half |
303aa43c215SJeff Kirsher 				   SUPPORTED_1000baseT_Full);
304aa43c215SJeff Kirsher 
30549cef10fSPhilippe Reynes 		advertising = (ADVERTISED_100baseT_Half |
306aa43c215SJeff Kirsher 				     ADVERTISED_100baseT_Full |
307aa43c215SJeff Kirsher 				     ADVERTISED_1000baseT_Half |
308aa43c215SJeff Kirsher 				     ADVERTISED_1000baseT_Full);
309aa43c215SJeff Kirsher 
31049cef10fSPhilippe Reynes 		ecmd->base.speed = adapter->ahw->link_speed;
31149cef10fSPhilippe Reynes 		ecmd->base.duplex = adapter->ahw->link_duplex;
31249cef10fSPhilippe Reynes 		ecmd->base.autoneg = adapter->ahw->link_autoneg;
313aa43c215SJeff Kirsher 
314aa43c215SJeff Kirsher 	} else if (adapter->ahw->port_type == QLCNIC_XGBE) {
3157e38d04bSSony Chacko 		u32 val = 0;
3164bd8e738SHimanshu Madhani 		val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR, &err);
3177e38d04bSSony Chacko 
318aa43c215SJeff Kirsher 		if (val == QLCNIC_PORT_MODE_802_3_AP) {
31949cef10fSPhilippe Reynes 			supported = SUPPORTED_1000baseT_Full;
32049cef10fSPhilippe Reynes 			advertising = ADVERTISED_1000baseT_Full;
321aa43c215SJeff Kirsher 		} else {
32249cef10fSPhilippe Reynes 			supported = SUPPORTED_10000baseT_Full;
32349cef10fSPhilippe Reynes 			advertising = ADVERTISED_10000baseT_Full;
324aa43c215SJeff Kirsher 		}
325aa43c215SJeff Kirsher 
326b938662dSHimanshu Madhani 		if (netif_running(adapter->netdev) && ahw->has_link_events) {
327beb3d3a4SRajesh Borundia 			if (ahw->linkup) {
328beb3d3a4SRajesh Borundia 				reg = QLCRD32(adapter,
3294bd8e738SHimanshu Madhani 					      P3P_LINK_SPEED_REG(pcifn), &err);
3307e38d04bSSony Chacko 				speed = P3P_LINK_SPEED_VAL(pcifn, reg);
3317e38d04bSSony Chacko 				ahw->link_speed = speed * P3P_LINK_SPEED_MHZ;
332beb3d3a4SRajesh Borundia 			}
333beb3d3a4SRajesh Borundia 
33449cef10fSPhilippe Reynes 			ecmd->base.speed = ahw->link_speed;
33549cef10fSPhilippe Reynes 			ecmd->base.autoneg = ahw->link_autoneg;
33649cef10fSPhilippe Reynes 			ecmd->base.duplex = ahw->link_duplex;
337aa43c215SJeff Kirsher 			goto skip;
338aa43c215SJeff Kirsher 		}
339aa43c215SJeff Kirsher 
34049cef10fSPhilippe Reynes 		ecmd->base.speed = SPEED_UNKNOWN;
34149cef10fSPhilippe Reynes 		ecmd->base.duplex = DUPLEX_UNKNOWN;
34249cef10fSPhilippe Reynes 		ecmd->base.autoneg = AUTONEG_DISABLE;
343aa43c215SJeff Kirsher 	} else
344aa43c215SJeff Kirsher 		return -EIO;
345aa43c215SJeff Kirsher 
346aa43c215SJeff Kirsher skip:
34749cef10fSPhilippe Reynes 	ecmd->base.phy_address = adapter->ahw->physical_port;
348aa43c215SJeff Kirsher 
349aa43c215SJeff Kirsher 	switch (adapter->ahw->board_type) {
350aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_REF_QG:
351aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_4_GB:
352aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_4_GB_MM:
35349cef10fSPhilippe Reynes 		supported |= SUPPORTED_Autoneg;
35449cef10fSPhilippe Reynes 		advertising |= ADVERTISED_Autoneg;
355df561f66SGustavo A. R. Silva 		fallthrough;
356aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10G_CX4:
357aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10G_CX4_LP:
358aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10000_BASE_T:
35949cef10fSPhilippe Reynes 		supported |= SUPPORTED_TP;
36049cef10fSPhilippe Reynes 		advertising |= ADVERTISED_TP;
36149cef10fSPhilippe Reynes 		ecmd->base.port = PORT_TP;
36249cef10fSPhilippe Reynes 		ecmd->base.autoneg =  adapter->ahw->link_autoneg;
363aa43c215SJeff Kirsher 		break;
364aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_IMEZ:
365aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_XG_LOM:
366aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_HMEZ:
36749cef10fSPhilippe Reynes 		supported |= SUPPORTED_MII;
36849cef10fSPhilippe Reynes 		advertising |= ADVERTISED_MII;
36949cef10fSPhilippe Reynes 		ecmd->base.port = PORT_MII;
37049cef10fSPhilippe Reynes 		ecmd->base.autoneg = AUTONEG_DISABLE;
371aa43c215SJeff Kirsher 		break;
372aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS:
373aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10G_SFP_CT:
374aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10G_SFP_QT:
37549cef10fSPhilippe Reynes 		advertising |= ADVERTISED_TP;
37649cef10fSPhilippe Reynes 		supported |= SUPPORTED_TP;
377b938662dSHimanshu Madhani 		check_sfp_module = netif_running(adapter->netdev) &&
378b938662dSHimanshu Madhani 				   ahw->has_link_events;
379df561f66SGustavo A. R. Silva 		fallthrough;
380aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10G_XFP:
38149cef10fSPhilippe Reynes 		supported |= SUPPORTED_FIBRE;
38249cef10fSPhilippe Reynes 		advertising |= ADVERTISED_FIBRE;
38349cef10fSPhilippe Reynes 		ecmd->base.port = PORT_FIBRE;
38449cef10fSPhilippe Reynes 		ecmd->base.autoneg = AUTONEG_DISABLE;
385aa43c215SJeff Kirsher 		break;
386aa43c215SJeff Kirsher 	case QLCNIC_BRDTYPE_P3P_10G_TP:
387aa43c215SJeff Kirsher 		if (adapter->ahw->port_type == QLCNIC_XGBE) {
38849cef10fSPhilippe Reynes 			ecmd->base.autoneg = AUTONEG_DISABLE;
38949cef10fSPhilippe Reynes 			supported |= (SUPPORTED_FIBRE | SUPPORTED_TP);
39049cef10fSPhilippe Reynes 			advertising |=
391aa43c215SJeff Kirsher 				(ADVERTISED_FIBRE | ADVERTISED_TP);
39249cef10fSPhilippe Reynes 			ecmd->base.port = PORT_FIBRE;
393b938662dSHimanshu Madhani 			check_sfp_module = netif_running(adapter->netdev) &&
394b938662dSHimanshu Madhani 					   ahw->has_link_events;
395aa43c215SJeff Kirsher 		} else {
39649cef10fSPhilippe Reynes 			ecmd->base.autoneg = AUTONEG_ENABLE;
39749cef10fSPhilippe Reynes 			supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
39849cef10fSPhilippe Reynes 			advertising |=
399aa43c215SJeff Kirsher 				(ADVERTISED_TP | ADVERTISED_Autoneg);
40049cef10fSPhilippe Reynes 			ecmd->base.port = PORT_TP;
401aa43c215SJeff Kirsher 		}
402aa43c215SJeff Kirsher 		break;
403aa43c215SJeff Kirsher 	default:
404aa43c215SJeff Kirsher 		dev_err(&adapter->pdev->dev, "Unsupported board model %d\n",
405aa43c215SJeff Kirsher 			adapter->ahw->board_type);
406aa43c215SJeff Kirsher 		return -EIO;
407aa43c215SJeff Kirsher 	}
408aa43c215SJeff Kirsher 
409aa43c215SJeff Kirsher 	if (check_sfp_module) {
41079788450SSony Chacko 		switch (adapter->ahw->module_type) {
411aa43c215SJeff Kirsher 		case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
412aa43c215SJeff Kirsher 		case LINKEVENT_MODULE_OPTICAL_SRLR:
413aa43c215SJeff Kirsher 		case LINKEVENT_MODULE_OPTICAL_LRM:
414aa43c215SJeff Kirsher 		case LINKEVENT_MODULE_OPTICAL_SFP_1G:
41549cef10fSPhilippe Reynes 			ecmd->base.port = PORT_FIBRE;
416aa43c215SJeff Kirsher 			break;
417aa43c215SJeff Kirsher 		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE:
418aa43c215SJeff Kirsher 		case LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN:
419aa43c215SJeff Kirsher 		case LINKEVENT_MODULE_TWINAX:
42049cef10fSPhilippe Reynes 			ecmd->base.port = PORT_TP;
421aa43c215SJeff Kirsher 			break;
422aa43c215SJeff Kirsher 		default:
42349cef10fSPhilippe Reynes 			ecmd->base.port = PORT_OTHER;
424aa43c215SJeff Kirsher 		}
425aa43c215SJeff Kirsher 	}
426aa43c215SJeff Kirsher 
42749cef10fSPhilippe Reynes 	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
42849cef10fSPhilippe Reynes 						supported);
42949cef10fSPhilippe Reynes 	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
43049cef10fSPhilippe Reynes 						advertising);
43149cef10fSPhilippe Reynes 
432aa43c215SJeff Kirsher 	return 0;
433aa43c215SJeff Kirsher }
434aa43c215SJeff Kirsher 
qlcnic_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * ecmd)43549cef10fSPhilippe Reynes static int qlcnic_get_link_ksettings(struct net_device *dev,
43649cef10fSPhilippe Reynes 				     struct ethtool_link_ksettings *ecmd)
43721041400Sstephen hemminger {
43821041400Sstephen hemminger 	struct qlcnic_adapter *adapter = netdev_priv(dev);
43921041400Sstephen hemminger 
44021041400Sstephen hemminger 	if (qlcnic_82xx_check(adapter))
44149cef10fSPhilippe Reynes 		return qlcnic_82xx_get_link_ksettings(adapter, ecmd);
44221041400Sstephen hemminger 	else if (qlcnic_83xx_check(adapter))
44349cef10fSPhilippe Reynes 		return qlcnic_83xx_get_link_ksettings(adapter, ecmd);
44421041400Sstephen hemminger 
44521041400Sstephen hemminger 	return -EIO;
44621041400Sstephen hemminger }
44721041400Sstephen hemminger 
44821041400Sstephen hemminger 
qlcnic_set_port_config(struct qlcnic_adapter * adapter,const struct ethtool_link_ksettings * ecmd)4497e38d04bSSony Chacko static int qlcnic_set_port_config(struct qlcnic_adapter *adapter,
45049cef10fSPhilippe Reynes 				  const struct ethtool_link_ksettings *ecmd)
451aa43c215SJeff Kirsher {
4527e38d04bSSony Chacko 	u32 ret = 0, config = 0;
453aa43c215SJeff Kirsher 	/* read which mode */
45449cef10fSPhilippe Reynes 	if (ecmd->base.duplex)
455aa43c215SJeff Kirsher 		config |= 0x1;
456aa43c215SJeff Kirsher 
45749cef10fSPhilippe Reynes 	if (ecmd->base.autoneg)
458aa43c215SJeff Kirsher 		config |= 0x2;
459aa43c215SJeff Kirsher 
46049cef10fSPhilippe Reynes 	switch (ecmd->base.speed) {
461aa43c215SJeff Kirsher 	case SPEED_10:
462aa43c215SJeff Kirsher 		config |= (0 << 8);
463aa43c215SJeff Kirsher 		break;
464aa43c215SJeff Kirsher 	case SPEED_100:
465aa43c215SJeff Kirsher 		config |= (1 << 8);
466aa43c215SJeff Kirsher 		break;
467aa43c215SJeff Kirsher 	case SPEED_1000:
468aa43c215SJeff Kirsher 		config |= (10 << 8);
469aa43c215SJeff Kirsher 		break;
470aa43c215SJeff Kirsher 	default:
471aa43c215SJeff Kirsher 		return -EIO;
472aa43c215SJeff Kirsher 	}
473aa43c215SJeff Kirsher 
474aa43c215SJeff Kirsher 	ret = qlcnic_fw_cmd_set_port(adapter, config);
475aa43c215SJeff Kirsher 
476aa43c215SJeff Kirsher 	if (ret == QLCNIC_RCODE_NOT_SUPPORTED)
477aa43c215SJeff Kirsher 		return -EOPNOTSUPP;
478aa43c215SJeff Kirsher 	else if (ret)
479aa43c215SJeff Kirsher 		return -EIO;
4807e38d04bSSony Chacko 	return ret;
4817e38d04bSSony Chacko }
4827e38d04bSSony Chacko 
qlcnic_set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * ecmd)48349cef10fSPhilippe Reynes static int qlcnic_set_link_ksettings(struct net_device *dev,
48449cef10fSPhilippe Reynes 				     const struct ethtool_link_ksettings *ecmd)
4857e38d04bSSony Chacko {
4867e38d04bSSony Chacko 	u32 ret = 0;
4877e38d04bSSony Chacko 	struct qlcnic_adapter *adapter = netdev_priv(dev);
4887e38d04bSSony Chacko 
489f9c3fe2fSChopra, Manish 	if (qlcnic_83xx_check(adapter))
490f9c3fe2fSChopra, Manish 		qlcnic_83xx_get_port_type(adapter);
491f9c3fe2fSChopra, Manish 
4927e38d04bSSony Chacko 	if (adapter->ahw->port_type != QLCNIC_GBE)
4937e38d04bSSony Chacko 		return -EOPNOTSUPP;
4947e38d04bSSony Chacko 
4957e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
49649cef10fSPhilippe Reynes 		ret = qlcnic_83xx_set_link_ksettings(adapter, ecmd);
4977e38d04bSSony Chacko 	else
4987e38d04bSSony Chacko 		ret = qlcnic_set_port_config(adapter, ecmd);
4997e38d04bSSony Chacko 
5007e38d04bSSony Chacko 	if (!ret)
5017e38d04bSSony Chacko 		return ret;
502aa43c215SJeff Kirsher 
50349cef10fSPhilippe Reynes 	adapter->ahw->link_speed = ecmd->base.speed;
50449cef10fSPhilippe Reynes 	adapter->ahw->link_duplex = ecmd->base.duplex;
50549cef10fSPhilippe Reynes 	adapter->ahw->link_autoneg = ecmd->base.autoneg;
506aa43c215SJeff Kirsher 
507aa43c215SJeff Kirsher 	if (!netif_running(dev))
508aa43c215SJeff Kirsher 		return 0;
509aa43c215SJeff Kirsher 
510aa43c215SJeff Kirsher 	dev->netdev_ops->ndo_stop(dev);
511aa43c215SJeff Kirsher 	return dev->netdev_ops->ndo_open(dev);
512aa43c215SJeff Kirsher }
513aa43c215SJeff Kirsher 
qlcnic_82xx_get_registers(struct qlcnic_adapter * adapter,u32 * regs_buff)5147e38d04bSSony Chacko static int qlcnic_82xx_get_registers(struct qlcnic_adapter *adapter,
5157e38d04bSSony Chacko 				     u32 *regs_buff)
5167e38d04bSSony Chacko {
5174bd8e738SHimanshu Madhani 	int i, j = 0, err = 0;
5187e38d04bSSony Chacko 
5197e38d04bSSony Chacko 	for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++)
5207e38d04bSSony Chacko 		regs_buff[i] = QLC_SHARED_REG_RD32(adapter, diag_registers[j]);
5217e38d04bSSony Chacko 	j = 0;
5227e38d04bSSony Chacko 	while (ext_diag_registers[j] != -1)
5234bd8e738SHimanshu Madhani 		regs_buff[i++] = QLCRD32(adapter, ext_diag_registers[j++],
5244bd8e738SHimanshu Madhani 					 &err);
5257e38d04bSSony Chacko 	return i;
5267e38d04bSSony Chacko }
5277e38d04bSSony Chacko 
528aa43c215SJeff Kirsher static void
qlcnic_get_regs(struct net_device * dev,struct ethtool_regs * regs,void * p)529aa43c215SJeff Kirsher qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
530aa43c215SJeff Kirsher {
531aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
532aa43c215SJeff Kirsher 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
533aa43c215SJeff Kirsher 	struct qlcnic_host_sds_ring *sds_ring;
534710a1a49SPratik Pujar 	struct qlcnic_host_rds_ring *rds_rings;
535710a1a49SPratik Pujar 	struct qlcnic_host_tx_ring *tx_ring;
536aa43c215SJeff Kirsher 	u32 *regs_buff = p;
5377e38d04bSSony Chacko 	int ring, i = 0;
538aa43c215SJeff Kirsher 
539aa43c215SJeff Kirsher 	memset(p, 0, qlcnic_get_regs_len(dev));
5407e38d04bSSony Chacko 
541aa43c215SJeff Kirsher 	regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
542aa43c215SJeff Kirsher 		(adapter->ahw->revision_id << 16) | (adapter->pdev)->device;
543aa43c215SJeff Kirsher 
544aa43c215SJeff Kirsher 	regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
545aa43c215SJeff Kirsher 	regs_buff[1] = QLCNIC_MGMT_API_VERSION;
546aa43c215SJeff Kirsher 
5472f514c52SJitendra Kalsaria 	if (adapter->ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY)
5482f514c52SJitendra Kalsaria 		regs_buff[2] = adapter->ahw->max_vnic_func;
5492f514c52SJitendra Kalsaria 
5507e38d04bSSony Chacko 	if (qlcnic_82xx_check(adapter))
5517e38d04bSSony Chacko 		i = qlcnic_82xx_get_registers(adapter, regs_buff);
5527e38d04bSSony Chacko 	else
5537e38d04bSSony Chacko 		i = qlcnic_83xx_get_registers(adapter, regs_buff);
554aa43c215SJeff Kirsher 
555aa43c215SJeff Kirsher 	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
556aa43c215SJeff Kirsher 		return;
557aa43c215SJeff Kirsher 
558710a1a49SPratik Pujar 	/* Marker btw regs and TX ring count */
559710a1a49SPratik Pujar 	regs_buff[i++] = 0xFFEFCDAB;
560aa43c215SJeff Kirsher 
56134e8c406SHimanshu Madhani 	regs_buff[i++] = adapter->drv_tx_rings; /* No. of TX ring */
56234e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
563710a1a49SPratik Pujar 		tx_ring = &adapter->tx_ring[ring];
564710a1a49SPratik Pujar 		regs_buff[i++] = le32_to_cpu(*(tx_ring->hw_consumer));
565710a1a49SPratik Pujar 		regs_buff[i++] = tx_ring->sw_consumer;
566710a1a49SPratik Pujar 		regs_buff[i++] = readl(tx_ring->crb_cmd_producer);
567710a1a49SPratik Pujar 		regs_buff[i++] = tx_ring->producer;
568710a1a49SPratik Pujar 		if (tx_ring->crb_intr_mask)
569710a1a49SPratik Pujar 			regs_buff[i++] = readl(tx_ring->crb_intr_mask);
570710a1a49SPratik Pujar 		else
571710a1a49SPratik Pujar 			regs_buff[i++] = QLCNIC_TX_INTR_NOT_CONFIGURED;
572710a1a49SPratik Pujar 	}
573aa43c215SJeff Kirsher 
574710a1a49SPratik Pujar 	regs_buff[i++] = adapter->max_rds_rings; /* No. of RX ring */
575710a1a49SPratik Pujar 	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
576710a1a49SPratik Pujar 		rds_rings = &recv_ctx->rds_rings[ring];
577710a1a49SPratik Pujar 		regs_buff[i++] = readl(rds_rings->crb_rcv_producer);
578710a1a49SPratik Pujar 		regs_buff[i++] = rds_rings->producer;
579710a1a49SPratik Pujar 	}
580aa43c215SJeff Kirsher 
58134e8c406SHimanshu Madhani 	regs_buff[i++] = adapter->drv_sds_rings; /* No. of SDS ring */
58234e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_sds_rings; ring++) {
583aa43c215SJeff Kirsher 		sds_ring = &(recv_ctx->sds_rings[ring]);
584aa43c215SJeff Kirsher 		regs_buff[i++] = readl(sds_ring->crb_sts_consumer);
585710a1a49SPratik Pujar 		regs_buff[i++] = sds_ring->consumer;
586710a1a49SPratik Pujar 		regs_buff[i++] = readl(sds_ring->crb_intr_mask);
587aa43c215SJeff Kirsher 	}
588aa43c215SJeff Kirsher }
589aa43c215SJeff Kirsher 
qlcnic_test_link(struct net_device * dev)590aa43c215SJeff Kirsher static u32 qlcnic_test_link(struct net_device *dev)
591aa43c215SJeff Kirsher {
592aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
5934bd8e738SHimanshu Madhani 	int err = 0;
594aa43c215SJeff Kirsher 	u32 val;
595aa43c215SJeff Kirsher 
5967e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter)) {
5977e38d04bSSony Chacko 		val = qlcnic_83xx_test_link(adapter);
5987e38d04bSSony Chacko 		return (val & 1) ? 0 : 1;
5997e38d04bSSony Chacko 	}
6004bd8e738SHimanshu Madhani 	val = QLCRD32(adapter, CRB_XG_STATE_P3P, &err);
6014bd8e738SHimanshu Madhani 	if (err == -EIO)
6024bd8e738SHimanshu Madhani 		return err;
603aa43c215SJeff Kirsher 	val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val);
604aa43c215SJeff Kirsher 	return (val == XG_LINK_UP_P3P) ? 0 : 1;
605aa43c215SJeff Kirsher }
606aa43c215SJeff Kirsher 
607aa43c215SJeff Kirsher static int
qlcnic_get_eeprom(struct net_device * dev,struct ethtool_eeprom * eeprom,u8 * bytes)608aa43c215SJeff Kirsher qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
609aa43c215SJeff Kirsher 		      u8 *bytes)
610aa43c215SJeff Kirsher {
611aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
612aa43c215SJeff Kirsher 	int offset;
6137e38d04bSSony Chacko 	int ret = -1;
614aa43c215SJeff Kirsher 
6157e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
6167e38d04bSSony Chacko 		return 0;
617aa43c215SJeff Kirsher 	if (eeprom->len == 0)
618aa43c215SJeff Kirsher 		return -EINVAL;
619aa43c215SJeff Kirsher 
620aa43c215SJeff Kirsher 	eeprom->magic = (adapter->pdev)->vendor |
621aa43c215SJeff Kirsher 			((adapter->pdev)->device << 16);
622aa43c215SJeff Kirsher 	offset = eeprom->offset;
623aa43c215SJeff Kirsher 
6247e38d04bSSony Chacko 	if (qlcnic_82xx_check(adapter))
625aa43c215SJeff Kirsher 		ret = qlcnic_rom_fast_read_words(adapter, offset, bytes,
626aa43c215SJeff Kirsher 						 eeprom->len);
627aa43c215SJeff Kirsher 	if (ret < 0)
628aa43c215SJeff Kirsher 		return ret;
629aa43c215SJeff Kirsher 
630aa43c215SJeff Kirsher 	return 0;
631aa43c215SJeff Kirsher }
632aa43c215SJeff Kirsher 
633aa43c215SJeff Kirsher static void
qlcnic_get_ringparam(struct net_device * dev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)634aa43c215SJeff Kirsher qlcnic_get_ringparam(struct net_device *dev,
63574624944SHao Chen 		     struct ethtool_ringparam *ring,
63674624944SHao Chen 		     struct kernel_ethtool_ringparam *kernel_ring,
63774624944SHao Chen 		     struct netlink_ext_ack *extack)
638aa43c215SJeff Kirsher {
639aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
640aa43c215SJeff Kirsher 
641aa43c215SJeff Kirsher 	ring->rx_pending = adapter->num_rxd;
642aa43c215SJeff Kirsher 	ring->rx_jumbo_pending = adapter->num_jumbo_rxd;
643aa43c215SJeff Kirsher 	ring->tx_pending = adapter->num_txd;
644aa43c215SJeff Kirsher 
645aa43c215SJeff Kirsher 	ring->rx_max_pending = adapter->max_rxd;
646aa43c215SJeff Kirsher 	ring->rx_jumbo_max_pending = adapter->max_jumbo_rxd;
647aa43c215SJeff Kirsher 	ring->tx_max_pending = MAX_CMD_DESCRIPTORS;
648aa43c215SJeff Kirsher }
649aa43c215SJeff Kirsher 
650aa43c215SJeff Kirsher static u32
qlcnic_validate_ringparam(u32 val,u32 min,u32 max,char * r_name)651aa43c215SJeff Kirsher qlcnic_validate_ringparam(u32 val, u32 min, u32 max, char *r_name)
652aa43c215SJeff Kirsher {
653aa43c215SJeff Kirsher 	u32 num_desc;
654aa43c215SJeff Kirsher 	num_desc = max(val, min);
655aa43c215SJeff Kirsher 	num_desc = min(num_desc, max);
656aa43c215SJeff Kirsher 	num_desc = roundup_pow_of_two(num_desc);
657aa43c215SJeff Kirsher 
658aa43c215SJeff Kirsher 	if (val != num_desc) {
659aa43c215SJeff Kirsher 		printk(KERN_INFO "%s: setting %s ring size %d instead of %d\n",
660aa43c215SJeff Kirsher 		       qlcnic_driver_name, r_name, num_desc, val);
661aa43c215SJeff Kirsher 	}
662aa43c215SJeff Kirsher 
663aa43c215SJeff Kirsher 	return num_desc;
664aa43c215SJeff Kirsher }
665aa43c215SJeff Kirsher 
666aa43c215SJeff Kirsher static int
qlcnic_set_ringparam(struct net_device * dev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)667aa43c215SJeff Kirsher qlcnic_set_ringparam(struct net_device *dev,
66874624944SHao Chen 		     struct ethtool_ringparam *ring,
66974624944SHao Chen 		     struct kernel_ethtool_ringparam *kernel_ring,
67074624944SHao Chen 		     struct netlink_ext_ack *extack)
671aa43c215SJeff Kirsher {
672aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
673aa43c215SJeff Kirsher 	u16 num_rxd, num_jumbo_rxd, num_txd;
674aa43c215SJeff Kirsher 
675aa43c215SJeff Kirsher 	if (ring->rx_mini_pending)
676aa43c215SJeff Kirsher 		return -EOPNOTSUPP;
677aa43c215SJeff Kirsher 
678aa43c215SJeff Kirsher 	num_rxd = qlcnic_validate_ringparam(ring->rx_pending,
679aa43c215SJeff Kirsher 			MIN_RCV_DESCRIPTORS, adapter->max_rxd, "rx");
680aa43c215SJeff Kirsher 
681aa43c215SJeff Kirsher 	num_jumbo_rxd = qlcnic_validate_ringparam(ring->rx_jumbo_pending,
682aa43c215SJeff Kirsher 			MIN_JUMBO_DESCRIPTORS, adapter->max_jumbo_rxd,
683aa43c215SJeff Kirsher 						"rx jumbo");
684aa43c215SJeff Kirsher 
685aa43c215SJeff Kirsher 	num_txd = qlcnic_validate_ringparam(ring->tx_pending,
686aa43c215SJeff Kirsher 			MIN_CMD_DESCRIPTORS, MAX_CMD_DESCRIPTORS, "tx");
687aa43c215SJeff Kirsher 
688aa43c215SJeff Kirsher 	if (num_rxd == adapter->num_rxd && num_txd == adapter->num_txd &&
689aa43c215SJeff Kirsher 			num_jumbo_rxd == adapter->num_jumbo_rxd)
690aa43c215SJeff Kirsher 		return 0;
691aa43c215SJeff Kirsher 
692aa43c215SJeff Kirsher 	adapter->num_rxd = num_rxd;
693aa43c215SJeff Kirsher 	adapter->num_jumbo_rxd = num_jumbo_rxd;
694aa43c215SJeff Kirsher 	adapter->num_txd = num_txd;
695aa43c215SJeff Kirsher 
696aa43c215SJeff Kirsher 	return qlcnic_reset_context(adapter);
697aa43c215SJeff Kirsher }
698aa43c215SJeff Kirsher 
qlcnic_validate_ring_count(struct qlcnic_adapter * adapter,u8 rx_ring,u8 tx_ring)69934e8c406SHimanshu Madhani static int qlcnic_validate_ring_count(struct qlcnic_adapter *adapter,
70034e8c406SHimanshu Madhani 				      u8 rx_ring, u8 tx_ring)
70134e8c406SHimanshu Madhani {
702f9566265SHimanshu Madhani 	if (rx_ring == 0 || tx_ring == 0)
703f9566265SHimanshu Madhani 		return -EINVAL;
704f9566265SHimanshu Madhani 
70534e8c406SHimanshu Madhani 	if (rx_ring != 0) {
70634e8c406SHimanshu Madhani 		if (rx_ring > adapter->max_sds_rings) {
707f9566265SHimanshu Madhani 			netdev_err(adapter->netdev,
708f9566265SHimanshu Madhani 				   "Invalid ring count, SDS ring count %d should not be greater than max %d driver sds rings.\n",
70934e8c406SHimanshu Madhani 				   rx_ring, adapter->max_sds_rings);
71034e8c406SHimanshu Madhani 			return -EINVAL;
71134e8c406SHimanshu Madhani 		}
71234e8c406SHimanshu Madhani 	}
71334e8c406SHimanshu Madhani 
71434e8c406SHimanshu Madhani 	if (tx_ring != 0) {
715b17a44d8SHimanshu Madhani 		if (tx_ring > adapter->max_tx_rings) {
71634e8c406SHimanshu Madhani 			netdev_err(adapter->netdev,
71734e8c406SHimanshu Madhani 				   "Invalid ring count, Tx ring count %d should not be greater than max %d driver Tx rings.\n",
71834e8c406SHimanshu Madhani 				   tx_ring, adapter->max_tx_rings);
71934e8c406SHimanshu Madhani 			return -EINVAL;
72034e8c406SHimanshu Madhani 		}
72134e8c406SHimanshu Madhani 	}
72234e8c406SHimanshu Madhani 
72334e8c406SHimanshu Madhani 	return 0;
72434e8c406SHimanshu Madhani }
72534e8c406SHimanshu Madhani 
qlcnic_get_channels(struct net_device * dev,struct ethtool_channels * channel)726aa43c215SJeff Kirsher static void qlcnic_get_channels(struct net_device *dev,
727aa43c215SJeff Kirsher 		struct ethtool_channels *channel)
728aa43c215SJeff Kirsher {
729aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
730aa43c215SJeff Kirsher 
73134e8c406SHimanshu Madhani 	channel->max_rx = adapter->max_sds_rings;
73234e8c406SHimanshu Madhani 	channel->max_tx = adapter->max_tx_rings;
73334e8c406SHimanshu Madhani 	channel->rx_count = adapter->drv_sds_rings;
73434e8c406SHimanshu Madhani 	channel->tx_count = adapter->drv_tx_rings;
735aa43c215SJeff Kirsher }
736aa43c215SJeff Kirsher 
qlcnic_set_channels(struct net_device * dev,struct ethtool_channels * channel)737aa43c215SJeff Kirsher static int qlcnic_set_channels(struct net_device *dev,
738aa43c215SJeff Kirsher 			       struct ethtool_channels *channel)
739aa43c215SJeff Kirsher {
740aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
741aa43c215SJeff Kirsher 	int err;
742aa43c215SJeff Kirsher 
74318e0d625SShahed Shaikh 	if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) {
74418e0d625SShahed Shaikh 		netdev_err(dev, "No RSS/TSS support in non MSI-X mode\n");
74518e0d625SShahed Shaikh 		return -EINVAL;
74618e0d625SShahed Shaikh 	}
74718e0d625SShahed Shaikh 
748aa4a1f7dSHimanshu Madhani 	if (channel->other_count || channel->combined_count)
749aa43c215SJeff Kirsher 		return -EINVAL;
750aa43c215SJeff Kirsher 
75134e8c406SHimanshu Madhani 	err = qlcnic_validate_ring_count(adapter, channel->rx_count,
75234e8c406SHimanshu Madhani 					 channel->tx_count);
753aa43c215SJeff Kirsher 	if (err)
754aa43c215SJeff Kirsher 		return err;
75534e8c406SHimanshu Madhani 
75618e0d625SShahed Shaikh 	if (adapter->drv_sds_rings != channel->rx_count) {
75734e8c406SHimanshu Madhani 		err = qlcnic_validate_rings(adapter, channel->rx_count,
75834e8c406SHimanshu Madhani 					    QLCNIC_RX_QUEUE);
75934e8c406SHimanshu Madhani 		if (err) {
76034e8c406SHimanshu Madhani 			netdev_err(dev, "Unable to configure %u SDS rings\n",
76134e8c406SHimanshu Madhani 				   channel->rx_count);
76234e8c406SHimanshu Madhani 			return err;
76334e8c406SHimanshu Madhani 		}
764cb9327d5SHimanshu Madhani 		adapter->drv_rss_rings = channel->rx_count;
765aa4a1f7dSHimanshu Madhani 	}
766aa43c215SJeff Kirsher 
76718e0d625SShahed Shaikh 	if (adapter->drv_tx_rings != channel->tx_count) {
76834e8c406SHimanshu Madhani 		err = qlcnic_validate_rings(adapter, channel->tx_count,
76934e8c406SHimanshu Madhani 					    QLCNIC_TX_QUEUE);
77034e8c406SHimanshu Madhani 		if (err) {
77134e8c406SHimanshu Madhani 			netdev_err(dev, "Unable to configure %u Tx rings\n",
77234e8c406SHimanshu Madhani 				   channel->tx_count);
773aa4a1f7dSHimanshu Madhani 			return err;
77434e8c406SHimanshu Madhani 		}
775cb9327d5SHimanshu Madhani 		adapter->drv_tss_rings = channel->tx_count;
776aa4a1f7dSHimanshu Madhani 	}
777aa4a1f7dSHimanshu Madhani 
778cb9327d5SHimanshu Madhani 	adapter->flags |= QLCNIC_TSS_RSS;
779cb9327d5SHimanshu Madhani 
780cb9327d5SHimanshu Madhani 	err = qlcnic_setup_rings(adapter);
78134e8c406SHimanshu Madhani 	netdev_info(dev, "Allocated %d SDS rings and %d Tx rings\n",
78234e8c406SHimanshu Madhani 		    adapter->drv_sds_rings, adapter->drv_tx_rings);
78334e8c406SHimanshu Madhani 
784aa43c215SJeff Kirsher 	return err;
785aa43c215SJeff Kirsher }
786aa43c215SJeff Kirsher 
787aa43c215SJeff Kirsher static void
qlcnic_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)788aa43c215SJeff Kirsher qlcnic_get_pauseparam(struct net_device *netdev,
789aa43c215SJeff Kirsher 			  struct ethtool_pauseparam *pause)
790aa43c215SJeff Kirsher {
791aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
79279788450SSony Chacko 	int port = adapter->ahw->physical_port;
7934bd8e738SHimanshu Madhani 	int err = 0;
794aa43c215SJeff Kirsher 	__u32 val;
795aa43c215SJeff Kirsher 
7967e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter)) {
7977e38d04bSSony Chacko 		qlcnic_83xx_get_pauseparam(adapter, pause);
7987e38d04bSSony Chacko 		return;
7997e38d04bSSony Chacko 	}
800aa43c215SJeff Kirsher 	if (adapter->ahw->port_type == QLCNIC_GBE) {
801aa43c215SJeff Kirsher 		if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
802aa43c215SJeff Kirsher 			return;
803aa43c215SJeff Kirsher 		/* get flow control settings */
8044bd8e738SHimanshu Madhani 		val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
8054bd8e738SHimanshu Madhani 		if (err == -EIO)
8064bd8e738SHimanshu Madhani 			return;
807aa43c215SJeff Kirsher 		pause->rx_pause = qlcnic_gb_get_rx_flowctl(val);
8084bd8e738SHimanshu Madhani 		val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
8094bd8e738SHimanshu Madhani 		if (err == -EIO)
8104bd8e738SHimanshu Madhani 			return;
811aa43c215SJeff Kirsher 		switch (port) {
812aa43c215SJeff Kirsher 		case 0:
813aa43c215SJeff Kirsher 			pause->tx_pause = !(qlcnic_gb_get_gb0_mask(val));
814aa43c215SJeff Kirsher 			break;
815aa43c215SJeff Kirsher 		case 1:
816aa43c215SJeff Kirsher 			pause->tx_pause = !(qlcnic_gb_get_gb1_mask(val));
817aa43c215SJeff Kirsher 			break;
818aa43c215SJeff Kirsher 		case 2:
819aa43c215SJeff Kirsher 			pause->tx_pause = !(qlcnic_gb_get_gb2_mask(val));
820aa43c215SJeff Kirsher 			break;
821aa43c215SJeff Kirsher 		case 3:
822aa43c215SJeff Kirsher 		default:
823aa43c215SJeff Kirsher 			pause->tx_pause = !(qlcnic_gb_get_gb3_mask(val));
824aa43c215SJeff Kirsher 			break;
825aa43c215SJeff Kirsher 		}
826aa43c215SJeff Kirsher 	} else if (adapter->ahw->port_type == QLCNIC_XGBE) {
827aa43c215SJeff Kirsher 		if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
828aa43c215SJeff Kirsher 			return;
829aa43c215SJeff Kirsher 		pause->rx_pause = 1;
8304bd8e738SHimanshu Madhani 		val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
8314bd8e738SHimanshu Madhani 		if (err == -EIO)
8324bd8e738SHimanshu Madhani 			return;
833aa43c215SJeff Kirsher 		if (port == 0)
834aa43c215SJeff Kirsher 			pause->tx_pause = !(qlcnic_xg_get_xg0_mask(val));
835aa43c215SJeff Kirsher 		else
836aa43c215SJeff Kirsher 			pause->tx_pause = !(qlcnic_xg_get_xg1_mask(val));
837aa43c215SJeff Kirsher 	} else {
838aa43c215SJeff Kirsher 		dev_err(&netdev->dev, "Unknown board type: %x\n",
839aa43c215SJeff Kirsher 					adapter->ahw->port_type);
840aa43c215SJeff Kirsher 	}
841aa43c215SJeff Kirsher }
842aa43c215SJeff Kirsher 
843aa43c215SJeff Kirsher static int
qlcnic_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)844aa43c215SJeff Kirsher qlcnic_set_pauseparam(struct net_device *netdev,
845aa43c215SJeff Kirsher 			  struct ethtool_pauseparam *pause)
846aa43c215SJeff Kirsher {
847aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
84879788450SSony Chacko 	int port = adapter->ahw->physical_port;
8494bd8e738SHimanshu Madhani 	int err = 0;
850aa43c215SJeff Kirsher 	__u32 val;
851aa43c215SJeff Kirsher 
8527e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
8537e38d04bSSony Chacko 		return qlcnic_83xx_set_pauseparam(adapter, pause);
8547e38d04bSSony Chacko 
855aa43c215SJeff Kirsher 	/* read mode */
856aa43c215SJeff Kirsher 	if (adapter->ahw->port_type == QLCNIC_GBE) {
857aa43c215SJeff Kirsher 		if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS))
858aa43c215SJeff Kirsher 			return -EIO;
859aa43c215SJeff Kirsher 		/* set flow control */
8604bd8e738SHimanshu Madhani 		val = QLCRD32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), &err);
8614bd8e738SHimanshu Madhani 		if (err == -EIO)
8624bd8e738SHimanshu Madhani 			return err;
863aa43c215SJeff Kirsher 
864aa43c215SJeff Kirsher 		if (pause->rx_pause)
865aa43c215SJeff Kirsher 			qlcnic_gb_rx_flowctl(val);
866aa43c215SJeff Kirsher 		else
867aa43c215SJeff Kirsher 			qlcnic_gb_unset_rx_flowctl(val);
868aa43c215SJeff Kirsher 
869aa43c215SJeff Kirsher 		QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port),
870aa43c215SJeff Kirsher 				val);
8717e38d04bSSony Chacko 		QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val);
872aa43c215SJeff Kirsher 		/* set autoneg */
8734bd8e738SHimanshu Madhani 		val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, &err);
8744bd8e738SHimanshu Madhani 		if (err == -EIO)
8754bd8e738SHimanshu Madhani 			return err;
876aa43c215SJeff Kirsher 		switch (port) {
877aa43c215SJeff Kirsher 		case 0:
878aa43c215SJeff Kirsher 			if (pause->tx_pause)
879aa43c215SJeff Kirsher 				qlcnic_gb_unset_gb0_mask(val);
880aa43c215SJeff Kirsher 			else
881aa43c215SJeff Kirsher 				qlcnic_gb_set_gb0_mask(val);
882aa43c215SJeff Kirsher 			break;
883aa43c215SJeff Kirsher 		case 1:
884aa43c215SJeff Kirsher 			if (pause->tx_pause)
885aa43c215SJeff Kirsher 				qlcnic_gb_unset_gb1_mask(val);
886aa43c215SJeff Kirsher 			else
887aa43c215SJeff Kirsher 				qlcnic_gb_set_gb1_mask(val);
888aa43c215SJeff Kirsher 			break;
889aa43c215SJeff Kirsher 		case 2:
890aa43c215SJeff Kirsher 			if (pause->tx_pause)
891aa43c215SJeff Kirsher 				qlcnic_gb_unset_gb2_mask(val);
892aa43c215SJeff Kirsher 			else
893aa43c215SJeff Kirsher 				qlcnic_gb_set_gb2_mask(val);
894aa43c215SJeff Kirsher 			break;
895aa43c215SJeff Kirsher 		case 3:
896aa43c215SJeff Kirsher 		default:
897aa43c215SJeff Kirsher 			if (pause->tx_pause)
898aa43c215SJeff Kirsher 				qlcnic_gb_unset_gb3_mask(val);
899aa43c215SJeff Kirsher 			else
900aa43c215SJeff Kirsher 				qlcnic_gb_set_gb3_mask(val);
901aa43c215SJeff Kirsher 			break;
902aa43c215SJeff Kirsher 		}
903aa43c215SJeff Kirsher 		QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
904aa43c215SJeff Kirsher 	} else if (adapter->ahw->port_type == QLCNIC_XGBE) {
905aa43c215SJeff Kirsher 		if (!pause->rx_pause || pause->autoneg)
906aa43c215SJeff Kirsher 			return -EOPNOTSUPP;
907aa43c215SJeff Kirsher 
908aa43c215SJeff Kirsher 		if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
909aa43c215SJeff Kirsher 			return -EIO;
910aa43c215SJeff Kirsher 
9114bd8e738SHimanshu Madhani 		val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, &err);
9124bd8e738SHimanshu Madhani 		if (err == -EIO)
9134bd8e738SHimanshu Madhani 			return err;
914aa43c215SJeff Kirsher 		if (port == 0) {
915aa43c215SJeff Kirsher 			if (pause->tx_pause)
916aa43c215SJeff Kirsher 				qlcnic_xg_unset_xg0_mask(val);
917aa43c215SJeff Kirsher 			else
918aa43c215SJeff Kirsher 				qlcnic_xg_set_xg0_mask(val);
919aa43c215SJeff Kirsher 		} else {
920aa43c215SJeff Kirsher 			if (pause->tx_pause)
921aa43c215SJeff Kirsher 				qlcnic_xg_unset_xg1_mask(val);
922aa43c215SJeff Kirsher 			else
923aa43c215SJeff Kirsher 				qlcnic_xg_set_xg1_mask(val);
924aa43c215SJeff Kirsher 		}
925aa43c215SJeff Kirsher 		QLCWR32(adapter, QLCNIC_NIU_XG_PAUSE_CTL, val);
926aa43c215SJeff Kirsher 	} else {
927aa43c215SJeff Kirsher 		dev_err(&netdev->dev, "Unknown board type: %x\n",
928aa43c215SJeff Kirsher 				adapter->ahw->port_type);
929aa43c215SJeff Kirsher 	}
930aa43c215SJeff Kirsher 	return 0;
931aa43c215SJeff Kirsher }
932aa43c215SJeff Kirsher 
qlcnic_reg_test(struct net_device * dev)933aa43c215SJeff Kirsher static int qlcnic_reg_test(struct net_device *dev)
934aa43c215SJeff Kirsher {
935aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
936aa43c215SJeff Kirsher 	u32 data_read;
9374bd8e738SHimanshu Madhani 	int err = 0;
938aa43c215SJeff Kirsher 
9397e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
9407e38d04bSSony Chacko 		return qlcnic_83xx_reg_test(adapter);
9417e38d04bSSony Chacko 
9424bd8e738SHimanshu Madhani 	data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0), &err);
9434bd8e738SHimanshu Madhani 	if (err == -EIO)
9444bd8e738SHimanshu Madhani 		return err;
945aa43c215SJeff Kirsher 	if ((data_read & 0xffff) != adapter->pdev->vendor)
946aa43c215SJeff Kirsher 		return 1;
947aa43c215SJeff Kirsher 
948aa43c215SJeff Kirsher 	return 0;
949aa43c215SJeff Kirsher }
950aa43c215SJeff Kirsher 
qlcnic_eeprom_test(struct net_device * dev)9517e38d04bSSony Chacko static int qlcnic_eeprom_test(struct net_device *dev)
9527e38d04bSSony Chacko {
9537e38d04bSSony Chacko 	struct qlcnic_adapter *adapter = netdev_priv(dev);
9547e38d04bSSony Chacko 
9557e38d04bSSony Chacko 	if (qlcnic_82xx_check(adapter))
9567e38d04bSSony Chacko 		return 0;
9577e38d04bSSony Chacko 
9587e38d04bSSony Chacko 	return qlcnic_83xx_flash_test(adapter);
9597e38d04bSSony Chacko }
9607e38d04bSSony Chacko 
qlcnic_get_sset_count(struct net_device * dev,int sset)961aa43c215SJeff Kirsher static int qlcnic_get_sset_count(struct net_device *dev, int sset)
962aa43c215SJeff Kirsher {
9637e38d04bSSony Chacko 
964aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
965aa43c215SJeff Kirsher 	switch (sset) {
966aa43c215SJeff Kirsher 	case ETH_SS_TEST:
967aa43c215SJeff Kirsher 		return QLCNIC_TEST_LEN;
968aa43c215SJeff Kirsher 	case ETH_SS_STATS:
969d6e9c89aSShahed Shaikh 		return qlcnic_dev_statistics_len(adapter);
970aa43c215SJeff Kirsher 	default:
971aa43c215SJeff Kirsher 		return -EOPNOTSUPP;
972aa43c215SJeff Kirsher 	}
973aa43c215SJeff Kirsher }
974aa43c215SJeff Kirsher 
qlcnic_irq_test(struct net_device * netdev)975aa43c215SJeff Kirsher static int qlcnic_irq_test(struct net_device *netdev)
976aa43c215SJeff Kirsher {
977aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
97858ead415SJitendra Kalsaria 	struct qlcnic_hardware_context *ahw = adapter->ahw;
9797777de9aSAnirban Chakraborty 	struct qlcnic_cmd_args cmd;
98034e8c406SHimanshu Madhani 	int ret, drv_sds_rings = adapter->drv_sds_rings;
9813bf517dfSHimanshu Madhani 	int drv_tx_rings = adapter->drv_tx_rings;
98258ead415SJitendra Kalsaria 
98358ead415SJitendra Kalsaria 	if (qlcnic_83xx_check(adapter))
98458ead415SJitendra Kalsaria 		return qlcnic_83xx_interrupt_test(netdev);
985aa43c215SJeff Kirsher 
986aa43c215SJeff Kirsher 	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
987aa43c215SJeff Kirsher 		return -EIO;
988aa43c215SJeff Kirsher 
989aa43c215SJeff Kirsher 	ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST);
990aa43c215SJeff Kirsher 	if (ret)
99158ead415SJitendra Kalsaria 		goto clear_diag_irq;
992aa43c215SJeff Kirsher 
99358ead415SJitendra Kalsaria 	ahw->diag_cnt = 0;
994b6b4316cSShahed Shaikh 	ret = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
995b6b4316cSShahed Shaikh 	if (ret)
996b6b4316cSShahed Shaikh 		goto free_diag_res;
9977e2cf4feSSony Chacko 
99858ead415SJitendra Kalsaria 	cmd.req.arg[1] = ahw->pci_func;
9997e2cf4feSSony Chacko 	ret = qlcnic_issue_cmd(adapter, &cmd);
1000aa43c215SJeff Kirsher 	if (ret)
1001aa43c215SJeff Kirsher 		goto done;
1002aa43c215SJeff Kirsher 
10037e2cf4feSSony Chacko 	usleep_range(1000, 12000);
100458ead415SJitendra Kalsaria 	ret = !ahw->diag_cnt;
1005aa43c215SJeff Kirsher 
1006aa43c215SJeff Kirsher done:
10077e2cf4feSSony Chacko 	qlcnic_free_mbx_args(&cmd);
1008b6b4316cSShahed Shaikh 
1009b6b4316cSShahed Shaikh free_diag_res:
101034e8c406SHimanshu Madhani 	qlcnic_diag_free_res(netdev, drv_sds_rings);
1011aa43c215SJeff Kirsher 
101258ead415SJitendra Kalsaria clear_diag_irq:
101334e8c406SHimanshu Madhani 	adapter->drv_sds_rings = drv_sds_rings;
10143bf517dfSHimanshu Madhani 	adapter->drv_tx_rings = drv_tx_rings;
1015aa43c215SJeff Kirsher 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
1016aa4a1f7dSHimanshu Madhani 
1017aa43c215SJeff Kirsher 	return ret;
1018aa43c215SJeff Kirsher }
1019aa43c215SJeff Kirsher 
1020aa43c215SJeff Kirsher #define QLCNIC_ILB_PKT_SIZE		64
1021aa43c215SJeff Kirsher #define QLCNIC_NUM_ILB_PKT		16
1022aa43c215SJeff Kirsher #define QLCNIC_ILB_MAX_RCV_LOOP		10
1023d1a1105eSRajesh Borundia #define QLCNIC_LB_PKT_POLL_DELAY_MSEC	1
1024d1a1105eSRajesh Borundia #define QLCNIC_LB_PKT_POLL_COUNT	20
1025aa43c215SJeff Kirsher 
qlcnic_create_loopback_buff(unsigned char * data,u8 mac[])1026aa43c215SJeff Kirsher static void qlcnic_create_loopback_buff(unsigned char *data, u8 mac[])
1027aa43c215SJeff Kirsher {
1028a6afdb04SColin Ian King 	static const unsigned char random_data[] = {0xa8, 0x06, 0x45, 0x00};
1029aa43c215SJeff Kirsher 
1030aa43c215SJeff Kirsher 	memset(data, 0x4e, QLCNIC_ILB_PKT_SIZE);
1031aa43c215SJeff Kirsher 
1032aa43c215SJeff Kirsher 	memcpy(data, mac, ETH_ALEN);
1033aa43c215SJeff Kirsher 	memcpy(data + ETH_ALEN, mac, ETH_ALEN);
1034aa43c215SJeff Kirsher 
1035aa43c215SJeff Kirsher 	memcpy(data + 2 * ETH_ALEN, random_data, sizeof(random_data));
1036aa43c215SJeff Kirsher }
1037aa43c215SJeff Kirsher 
qlcnic_check_loopback_buff(unsigned char * data,u8 mac[])1038aa43c215SJeff Kirsher int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[])
1039aa43c215SJeff Kirsher {
1040aa43c215SJeff Kirsher 	unsigned char buff[QLCNIC_ILB_PKT_SIZE];
1041aa43c215SJeff Kirsher 	qlcnic_create_loopback_buff(buff, mac);
1042aa43c215SJeff Kirsher 	return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE);
1043aa43c215SJeff Kirsher }
1044aa43c215SJeff Kirsher 
qlcnic_do_lb_test(struct qlcnic_adapter * adapter,u8 mode)1045ba4468dbSJitendra Kalsaria int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
1046aa43c215SJeff Kirsher {
1047aa43c215SJeff Kirsher 	struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
1048aa43c215SJeff Kirsher 	struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0];
1049aa43c215SJeff Kirsher 	struct sk_buff *skb;
1050aa43c215SJeff Kirsher 	int i, loop, cnt = 0;
1051aa43c215SJeff Kirsher 
1052aa43c215SJeff Kirsher 	for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
1053dae2e9f4SPradeep A. Dalvi 		skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
105484460f01STom Seewald 		if (!skb)
105584460f01STom Seewald 			goto error;
1056aa43c215SJeff Kirsher 		qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
1057aa43c215SJeff Kirsher 		skb_put(skb, QLCNIC_ILB_PKT_SIZE);
105879788450SSony Chacko 		adapter->ahw->diag_cnt = 0;
1059aa43c215SJeff Kirsher 		qlcnic_xmit_frame(skb, adapter->netdev);
1060aa43c215SJeff Kirsher 		loop = 0;
10617e38d04bSSony Chacko 
1062aa43c215SJeff Kirsher 		do {
1063d1a1105eSRajesh Borundia 			msleep(QLCNIC_LB_PKT_POLL_DELAY_MSEC);
1064aa43c215SJeff Kirsher 			qlcnic_process_rcv_ring_diag(sds_ring);
1065d1a1105eSRajesh Borundia 			if (loop++ > QLCNIC_LB_PKT_POLL_COUNT)
1066aa43c215SJeff Kirsher 				break;
106779788450SSony Chacko 		} while (!adapter->ahw->diag_cnt);
1068aa43c215SJeff Kirsher 
1069aa43c215SJeff Kirsher 		dev_kfree_skb_any(skb);
1070aa43c215SJeff Kirsher 
107179788450SSony Chacko 		if (!adapter->ahw->diag_cnt)
10727e38d04bSSony Chacko 			dev_warn(&adapter->pdev->dev,
10737e38d04bSSony Chacko 				 "LB Test: packet #%d was not received\n",
10747e38d04bSSony Chacko 				 i + 1);
1075aa43c215SJeff Kirsher 		else
1076aa43c215SJeff Kirsher 			cnt++;
1077aa43c215SJeff Kirsher 	}
1078aa43c215SJeff Kirsher 	if (cnt != i) {
107984460f01STom Seewald error:
10807e38d04bSSony Chacko 		dev_err(&adapter->pdev->dev,
10817e38d04bSSony Chacko 			"LB Test: failed, TX[%d], RX[%d]\n", i, cnt);
10827e38d04bSSony Chacko 		if (mode != QLCNIC_ILB_MODE)
1083df3cfbe3SManish chopra 			dev_warn(&adapter->pdev->dev,
10847e38d04bSSony Chacko 				 "WARNING: Please check loopback cable\n");
1085aa43c215SJeff Kirsher 		return -1;
1086aa43c215SJeff Kirsher 	}
1087aa43c215SJeff Kirsher 	return 0;
1088aa43c215SJeff Kirsher }
1089aa43c215SJeff Kirsher 
qlcnic_loopback_test(struct net_device * netdev,u8 mode)109021041400Sstephen hemminger static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
1091aa43c215SJeff Kirsher {
1092aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
109334e8c406SHimanshu Madhani 	int drv_tx_rings = adapter->drv_tx_rings;
109434e8c406SHimanshu Madhani 	int drv_sds_rings = adapter->drv_sds_rings;
1095aa43c215SJeff Kirsher 	struct qlcnic_host_sds_ring *sds_ring;
10967e38d04bSSony Chacko 	struct qlcnic_hardware_context *ahw = adapter->ahw;
1097aa43c215SJeff Kirsher 	int loop = 0;
1098aa43c215SJeff Kirsher 	int ret;
1099aa43c215SJeff Kirsher 
11007e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
1101ba4468dbSJitendra Kalsaria 		return qlcnic_83xx_loopback_test(netdev, mode);
1102ba4468dbSJitendra Kalsaria 
11037e38d04bSSony Chacko 	if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
11047e38d04bSSony Chacko 		dev_info(&adapter->pdev->dev,
11057e38d04bSSony Chacko 			 "Firmware do not support loopback test\n");
1106aa43c215SJeff Kirsher 		return -EOPNOTSUPP;
1107aa43c215SJeff Kirsher 	}
1108ba4468dbSJitendra Kalsaria 
11097e38d04bSSony Chacko 	dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n",
1110aa43c215SJeff Kirsher 		 mode == QLCNIC_ILB_MODE ? "internal" : "external");
11117e38d04bSSony Chacko 	if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
11127e38d04bSSony Chacko 		dev_warn(&adapter->pdev->dev,
11137e38d04bSSony Chacko 			 "Loopback test not supported in nonprivileged mode\n");
1114aa43c215SJeff Kirsher 		return 0;
1115aa43c215SJeff Kirsher 	}
1116aa43c215SJeff Kirsher 
1117aa43c215SJeff Kirsher 	if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1118aa43c215SJeff Kirsher 		return -EBUSY;
1119aa43c215SJeff Kirsher 
1120aa43c215SJeff Kirsher 	ret = qlcnic_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST);
1121aa43c215SJeff Kirsher 	if (ret)
1122aa43c215SJeff Kirsher 		goto clear_it;
1123aa43c215SJeff Kirsher 
1124aa43c215SJeff Kirsher 	sds_ring = &adapter->recv_ctx->sds_rings[0];
1125aa43c215SJeff Kirsher 	ret = qlcnic_set_lb_mode(adapter, mode);
1126aa43c215SJeff Kirsher 	if (ret)
1127aa43c215SJeff Kirsher 		goto free_res;
1128aa43c215SJeff Kirsher 
11297e38d04bSSony Chacko 	ahw->diag_cnt = 0;
1130aa43c215SJeff Kirsher 	do {
1131aa43c215SJeff Kirsher 		msleep(500);
1132aa43c215SJeff Kirsher 		qlcnic_process_rcv_ring_diag(sds_ring);
1133aa43c215SJeff Kirsher 		if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) {
1134b9c11984SJitendra Kalsaria 			netdev_info(netdev,
1135b9c11984SJitendra Kalsaria 				    "Firmware didn't sent link up event to loopback request\n");
1136b9c11984SJitendra Kalsaria 			ret = -ETIMEDOUT;
1137aa43c215SJeff Kirsher 			goto free_res;
113879788450SSony Chacko 		} else if (adapter->ahw->diag_cnt) {
113979788450SSony Chacko 			ret = adapter->ahw->diag_cnt;
1140aa43c215SJeff Kirsher 			goto free_res;
1141aa43c215SJeff Kirsher 		}
11427e38d04bSSony Chacko 	} while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state));
1143ba4468dbSJitendra Kalsaria 
1144df3cfbe3SManish chopra 	ret = qlcnic_do_lb_test(adapter, mode);
1145ba4468dbSJitendra Kalsaria 
11467e2cf4feSSony Chacko 	qlcnic_clear_lb_mode(adapter, mode);
1147aa43c215SJeff Kirsher 
1148aa43c215SJeff Kirsher  free_res:
114934e8c406SHimanshu Madhani 	qlcnic_diag_free_res(netdev, drv_sds_rings);
1150aa43c215SJeff Kirsher 
1151aa43c215SJeff Kirsher  clear_it:
115234e8c406SHimanshu Madhani 	adapter->drv_sds_rings = drv_sds_rings;
115334e8c406SHimanshu Madhani 	adapter->drv_tx_rings = drv_tx_rings;
1154aa43c215SJeff Kirsher 	clear_bit(__QLCNIC_RESETTING, &adapter->state);
1155aa43c215SJeff Kirsher 	return ret;
1156aa43c215SJeff Kirsher }
1157aa43c215SJeff Kirsher 
1158aa43c215SJeff Kirsher static void
qlcnic_diag_test(struct net_device * dev,struct ethtool_test * eth_test,u64 * data)1159aa43c215SJeff Kirsher qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
1160aa43c215SJeff Kirsher 		     u64 *data)
1161aa43c215SJeff Kirsher {
1162aa43c215SJeff Kirsher 	memset(data, 0, sizeof(u64) * QLCNIC_TEST_LEN);
1163aa43c215SJeff Kirsher 
1164aa43c215SJeff Kirsher 	data[0] = qlcnic_reg_test(dev);
1165aa43c215SJeff Kirsher 	if (data[0])
1166aa43c215SJeff Kirsher 		eth_test->flags |= ETH_TEST_FL_FAILED;
1167aa43c215SJeff Kirsher 
1168aa43c215SJeff Kirsher 	data[1] = (u64) qlcnic_test_link(dev);
1169aa43c215SJeff Kirsher 	if (data[1])
1170aa43c215SJeff Kirsher 		eth_test->flags |= ETH_TEST_FL_FAILED;
1171aa43c215SJeff Kirsher 
1172aa43c215SJeff Kirsher 	if (eth_test->flags & ETH_TEST_FL_OFFLINE) {
1173aa43c215SJeff Kirsher 		data[2] = qlcnic_irq_test(dev);
1174aa43c215SJeff Kirsher 		if (data[2])
1175aa43c215SJeff Kirsher 			eth_test->flags |= ETH_TEST_FL_FAILED;
1176aa43c215SJeff Kirsher 
1177aa43c215SJeff Kirsher 		data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE);
1178aa43c215SJeff Kirsher 		if (data[3])
1179aa43c215SJeff Kirsher 			eth_test->flags |= ETH_TEST_FL_FAILED;
11807e38d04bSSony Chacko 
11812e3ea7e7SShahed Shaikh 		if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) {
11822e3ea7e7SShahed Shaikh 			data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE);
1183aa43c215SJeff Kirsher 			if (data[4])
1184aa43c215SJeff Kirsher 				eth_test->flags |= ETH_TEST_FL_FAILED;
11852e3ea7e7SShahed Shaikh 			eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
11862e3ea7e7SShahed Shaikh 		}
11872e3ea7e7SShahed Shaikh 
11882e3ea7e7SShahed Shaikh 		data[5] = qlcnic_eeprom_test(dev);
11892e3ea7e7SShahed Shaikh 		if (data[5])
11902e3ea7e7SShahed Shaikh 			eth_test->flags |= ETH_TEST_FL_FAILED;
1191aa43c215SJeff Kirsher 	}
1192aa43c215SJeff Kirsher }
1193aa43c215SJeff Kirsher 
1194aa43c215SJeff Kirsher static void
qlcnic_get_strings(struct net_device * dev,u32 stringset,u8 * data)1195aa43c215SJeff Kirsher qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
1196aa43c215SJeff Kirsher {
1197aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
11987e38d04bSSony Chacko 	int index, i, num_stats;
1199aa43c215SJeff Kirsher 
1200aa43c215SJeff Kirsher 	switch (stringset) {
1201aa43c215SJeff Kirsher 	case ETH_SS_TEST:
1202aa43c215SJeff Kirsher 		memcpy(data, *qlcnic_gstrings_test,
1203aa43c215SJeff Kirsher 		       QLCNIC_TEST_LEN * ETH_GSTRING_LEN);
1204aa43c215SJeff Kirsher 		break;
1205aa43c215SJeff Kirsher 	case ETH_SS_STATS:
1206f27c75b3SHimanshu Madhani 		num_stats = ARRAY_SIZE(qlcnic_tx_queue_stats_strings);
120734e8c406SHimanshu Madhani 		for (i = 0; i < adapter->drv_tx_rings; i++) {
1208aa4a1f7dSHimanshu Madhani 			for (index = 0; index < num_stats; index++) {
1209f27c75b3SHimanshu Madhani 				sprintf(data, "tx_queue_%d %s", i,
1210f27c75b3SHimanshu Madhani 					qlcnic_tx_queue_stats_strings[index]);
1211aa4a1f7dSHimanshu Madhani 				data += ETH_GSTRING_LEN;
1212aa4a1f7dSHimanshu Madhani 			}
1213aa4a1f7dSHimanshu Madhani 		}
1214aa4a1f7dSHimanshu Madhani 
1215aa43c215SJeff Kirsher 		for (index = 0; index < QLCNIC_STATS_LEN; index++) {
1216aa43c215SJeff Kirsher 			memcpy(data + index * ETH_GSTRING_LEN,
1217aa43c215SJeff Kirsher 			       qlcnic_gstrings_stats[index].stat_string,
1218aa43c215SJeff Kirsher 			       ETH_GSTRING_LEN);
1219aa43c215SJeff Kirsher 		}
1220aa4a1f7dSHimanshu Madhani 
12217e38d04bSSony Chacko 		if (qlcnic_83xx_check(adapter)) {
12227e38d04bSSony Chacko 			num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings);
12237e38d04bSSony Chacko 			for (i = 0; i < num_stats; i++, index++)
122454a8997cSJitendra Kalsaria 				memcpy(data + index * ETH_GSTRING_LEN,
12257e38d04bSSony Chacko 				       qlcnic_83xx_tx_stats_strings[i],
12267e38d04bSSony Chacko 				       ETH_GSTRING_LEN);
12277e38d04bSSony Chacko 			num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
12287e38d04bSSony Chacko 			for (i = 0; i < num_stats; i++, index++)
12297e38d04bSSony Chacko 				memcpy(data + index * ETH_GSTRING_LEN,
12307e38d04bSSony Chacko 				       qlcnic_83xx_mac_stats_strings[i],
12317e38d04bSSony Chacko 				       ETH_GSTRING_LEN);
12327e38d04bSSony Chacko 			num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings);
12337e38d04bSSony Chacko 			for (i = 0; i < num_stats; i++, index++)
12347e38d04bSSony Chacko 				memcpy(data + index * ETH_GSTRING_LEN,
12357e38d04bSSony Chacko 				       qlcnic_83xx_rx_stats_strings[i],
12367e38d04bSSony Chacko 				       ETH_GSTRING_LEN);
12377e38d04bSSony Chacko 			return;
12387e38d04bSSony Chacko 		} else {
12397e38d04bSSony Chacko 			num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings);
12407e38d04bSSony Chacko 			for (i = 0; i < num_stats; i++, index++)
12417e38d04bSSony Chacko 				memcpy(data + index * ETH_GSTRING_LEN,
12427e38d04bSSony Chacko 				       qlcnic_83xx_mac_stats_strings[i],
124354a8997cSJitendra Kalsaria 				       ETH_GSTRING_LEN);
124454a8997cSJitendra Kalsaria 		}
1245aa43c215SJeff Kirsher 		if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1246aa43c215SJeff Kirsher 			return;
12477e38d04bSSony Chacko 		num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats);
12487e38d04bSSony Chacko 		for (i = 0; i < num_stats; index++, i++) {
1249aa43c215SJeff Kirsher 			memcpy(data + index * ETH_GSTRING_LEN,
1250aa43c215SJeff Kirsher 			       qlcnic_device_gstrings_stats[i],
1251aa43c215SJeff Kirsher 			       ETH_GSTRING_LEN);
1252aa43c215SJeff Kirsher 		}
1253aa43c215SJeff Kirsher 	}
1254aa43c215SJeff Kirsher }
1255aa43c215SJeff Kirsher 
qlcnic_fill_stats(u64 * data,void * stats,int type)12569434dbfeSShahed Shaikh static u64 *qlcnic_fill_stats(u64 *data, void *stats, int type)
1257aa43c215SJeff Kirsher {
125854a8997cSJitendra Kalsaria 	if (type == QLCNIC_MAC_STATS) {
125954a8997cSJitendra Kalsaria 		struct qlcnic_mac_statistics *mac_stats =
126054a8997cSJitendra Kalsaria 					(struct qlcnic_mac_statistics *)stats;
12617e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames);
12627e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes);
12637e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts);
12647e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts);
12657e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt);
12667e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt);
12677e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts);
12687e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts);
12697e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts);
12707e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts);
12717e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts);
12727e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts);
12737e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts);
12747e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames);
12757e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes);
12767e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts);
12777e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts);
12787e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt);
12797e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt);
12807e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts);
12817e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts);
12827e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts);
12837e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts);
12847e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts);
12857e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts);
12867e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts);
12877e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error);
12887e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small);
12897e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large);
12907e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber);
12917e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped);
12927e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error);
12937e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(mac_stats->mac_align_error);
129454a8997cSJitendra Kalsaria 	} else if (type == QLCNIC_ESW_STATS) {
129554a8997cSJitendra Kalsaria 		struct __qlcnic_esw_statistics *esw_stats =
129654a8997cSJitendra Kalsaria 				(struct __qlcnic_esw_statistics *)stats;
12977e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(esw_stats->unicast_frames);
12987e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(esw_stats->multicast_frames);
12997e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(esw_stats->broadcast_frames);
13007e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(esw_stats->dropped_frames);
13017e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(esw_stats->errors);
13027e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(esw_stats->local_frames);
13037e38d04bSSony Chacko 		*data++ = QLCNIC_FILL_STATS(esw_stats->numbytes);
13047e38d04bSSony Chacko 	}
13059434dbfeSShahed Shaikh 	return data;
130654a8997cSJitendra Kalsaria }
1307aa43c215SJeff Kirsher 
qlcnic_update_stats(struct qlcnic_adapter * adapter)13081ac6762aSManish Chopra void qlcnic_update_stats(struct qlcnic_adapter *adapter)
1309f27c75b3SHimanshu Madhani {
1310a0eaf75cSRajesh Borundia 	struct qlcnic_tx_queue_stats tx_stats;
1311f27c75b3SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1312f27c75b3SHimanshu Madhani 	int ring;
1313f27c75b3SHimanshu Madhani 
1314a0eaf75cSRajesh Borundia 	memset(&tx_stats, 0, sizeof(tx_stats));
131534e8c406SHimanshu Madhani 	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
1316f27c75b3SHimanshu Madhani 		tx_ring = &adapter->tx_ring[ring];
1317a0eaf75cSRajesh Borundia 		tx_stats.xmit_on += tx_ring->tx_stats.xmit_on;
1318a0eaf75cSRajesh Borundia 		tx_stats.xmit_off += tx_ring->tx_stats.xmit_off;
1319a0eaf75cSRajesh Borundia 		tx_stats.xmit_called += tx_ring->tx_stats.xmit_called;
1320a0eaf75cSRajesh Borundia 		tx_stats.xmit_finished += tx_ring->tx_stats.xmit_finished;
1321a0eaf75cSRajesh Borundia 		tx_stats.tx_bytes += tx_ring->tx_stats.tx_bytes;
1322f27c75b3SHimanshu Madhani 	}
1323a0eaf75cSRajesh Borundia 
1324a0eaf75cSRajesh Borundia 	adapter->stats.xmit_on = tx_stats.xmit_on;
1325a0eaf75cSRajesh Borundia 	adapter->stats.xmit_off = tx_stats.xmit_off;
1326a0eaf75cSRajesh Borundia 	adapter->stats.xmitcalled = tx_stats.xmit_called;
1327a0eaf75cSRajesh Borundia 	adapter->stats.xmitfinished = tx_stats.xmit_finished;
1328a0eaf75cSRajesh Borundia 	adapter->stats.txbytes = tx_stats.tx_bytes;
1329f27c75b3SHimanshu Madhani }
1330f27c75b3SHimanshu Madhani 
qlcnic_fill_tx_queue_stats(u64 * data,void * stats)1331f27c75b3SHimanshu Madhani static u64 *qlcnic_fill_tx_queue_stats(u64 *data, void *stats)
1332f27c75b3SHimanshu Madhani {
1333f27c75b3SHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1334f27c75b3SHimanshu Madhani 
1335f27c75b3SHimanshu Madhani 	tx_ring = (struct qlcnic_host_tx_ring *)stats;
1336f27c75b3SHimanshu Madhani 
1337f27c75b3SHimanshu Madhani 	*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_on);
1338f27c75b3SHimanshu Madhani 	*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_off);
1339f27c75b3SHimanshu Madhani 	*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_called);
1340f27c75b3SHimanshu Madhani 	*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.xmit_finished);
1341f27c75b3SHimanshu Madhani 	*data++ = QLCNIC_FILL_STATS(tx_ring->tx_stats.tx_bytes);
1342f27c75b3SHimanshu Madhani 
1343f27c75b3SHimanshu Madhani 	return data;
1344f27c75b3SHimanshu Madhani }
1345f27c75b3SHimanshu Madhani 
qlcnic_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)13467e38d04bSSony Chacko static void qlcnic_get_ethtool_stats(struct net_device *dev,
1347aa43c215SJeff Kirsher 				     struct ethtool_stats *stats, u64 *data)
1348aa43c215SJeff Kirsher {
1349aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
1350aa4a1f7dSHimanshu Madhani 	struct qlcnic_host_tx_ring *tx_ring;
1351aa43c215SJeff Kirsher 	struct qlcnic_esw_statistics port_stats;
135254a8997cSJitendra Kalsaria 	struct qlcnic_mac_statistics mac_stats;
1353c0230301SManish Chopra 	int index, ret, length, size, ring;
13547e38d04bSSony Chacko 	char *p;
1355aa43c215SJeff Kirsher 
1356c0230301SManish Chopra 	memset(data, 0, stats->n_stats * sizeof(u64));
1357f27c75b3SHimanshu Madhani 
135879fdce05SColin Ian King 	for (ring = 0; ring < adapter->drv_tx_rings; ring++) {
13596c0fd0dfSManish Chopra 		if (adapter->is_up == QLCNIC_ADAPTER_UP_MAGIC) {
1360aa4a1f7dSHimanshu Madhani 			tx_ring = &adapter->tx_ring[ring];
1361f27c75b3SHimanshu Madhani 			data = qlcnic_fill_tx_queue_stats(data, tx_ring);
1362f27c75b3SHimanshu Madhani 			qlcnic_update_stats(adapter);
13633456399bSManish Chopra 		} else {
13643456399bSManish Chopra 			data += QLCNIC_TX_STATS_LEN;
1365aa4a1f7dSHimanshu Madhani 		}
1366aa4a1f7dSHimanshu Madhani 	}
1367f27c75b3SHimanshu Madhani 
13687e38d04bSSony Chacko 	length = QLCNIC_STATS_LEN;
13697e38d04bSSony Chacko 	for (index = 0; index < length; index++) {
13707e38d04bSSony Chacko 		p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset;
13717e38d04bSSony Chacko 		size = qlcnic_gstrings_stats[index].sizeof_stat;
13727e38d04bSSony Chacko 		*data++ = (size == sizeof(u64)) ? (*(u64 *)p) : ((*(u32 *)p));
1373aa43c215SJeff Kirsher 	}
1374aa43c215SJeff Kirsher 
13757e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter)) {
13767e38d04bSSony Chacko 		if (adapter->ahw->linkup)
13777e38d04bSSony Chacko 			qlcnic_83xx_get_stats(adapter, data);
13787e38d04bSSony Chacko 		return;
13797e38d04bSSony Chacko 	} else {
138054a8997cSJitendra Kalsaria 		/* Retrieve MAC statistics from firmware */
138154a8997cSJitendra Kalsaria 		memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics));
138254a8997cSJitendra Kalsaria 		qlcnic_get_mac_stats(adapter, &mac_stats);
13839434dbfeSShahed Shaikh 		data = qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS);
13847e38d04bSSony Chacko 	}
138554a8997cSJitendra Kalsaria 
1386aa43c215SJeff Kirsher 	if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
1387aa43c215SJeff Kirsher 		return;
1388aa43c215SJeff Kirsher 
1389aa43c215SJeff Kirsher 	memset(&port_stats, 0, sizeof(struct qlcnic_esw_statistics));
1390aa43c215SJeff Kirsher 	ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
1391aa43c215SJeff Kirsher 			QLCNIC_QUERY_RX_COUNTER, &port_stats.rx);
1392aa43c215SJeff Kirsher 	if (ret)
1393aa43c215SJeff Kirsher 		return;
1394aa43c215SJeff Kirsher 
13959434dbfeSShahed Shaikh 	data = qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS);
1396aa43c215SJeff Kirsher 	ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func,
1397aa43c215SJeff Kirsher 			QLCNIC_QUERY_TX_COUNTER, &port_stats.tx);
1398aa43c215SJeff Kirsher 	if (ret)
1399aa43c215SJeff Kirsher 		return;
1400aa43c215SJeff Kirsher 
14017e38d04bSSony Chacko 	qlcnic_fill_stats(data, &port_stats.tx, QLCNIC_ESW_STATS);
1402aa43c215SJeff Kirsher }
1403aa43c215SJeff Kirsher 
qlcnic_set_led(struct net_device * dev,enum ethtool_phys_id_state state)1404aa43c215SJeff Kirsher static int qlcnic_set_led(struct net_device *dev,
1405aa43c215SJeff Kirsher 			  enum ethtool_phys_id_state state)
1406aa43c215SJeff Kirsher {
1407aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
140834e8c406SHimanshu Madhani 	int drv_sds_rings = adapter->drv_sds_rings;
140910ee0faeSSucheta Chakraborty 	int err = -EIO, active = 1;
141010ee0faeSSucheta Chakraborty 
14117e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
1412d16951d9SHimanshu Madhani 		return qlcnic_83xx_set_led(dev, state);
1413d16951d9SHimanshu Madhani 
141479788450SSony Chacko 	if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
141510ee0faeSSucheta Chakraborty 		netdev_warn(dev, "LED test not supported for non "
141610ee0faeSSucheta Chakraborty 				"privilege function\n");
141710ee0faeSSucheta Chakraborty 		return -EOPNOTSUPP;
141810ee0faeSSucheta Chakraborty 	}
1419aa43c215SJeff Kirsher 
1420aa43c215SJeff Kirsher 	switch (state) {
1421aa43c215SJeff Kirsher 	case ETHTOOL_ID_ACTIVE:
1422728a98b8SSucheta Chakraborty 		if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state))
1423728a98b8SSucheta Chakraborty 			return -EBUSY;
1424728a98b8SSucheta Chakraborty 
142510ee0faeSSucheta Chakraborty 		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
142610ee0faeSSucheta Chakraborty 			break;
1427aa43c215SJeff Kirsher 
142810ee0faeSSucheta Chakraborty 		if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
142910ee0faeSSucheta Chakraborty 			if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
143010ee0faeSSucheta Chakraborty 				break;
1431aa43c215SJeff Kirsher 			set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
1432aa43c215SJeff Kirsher 		}
1433aa43c215SJeff Kirsher 
143410ee0faeSSucheta Chakraborty 		if (adapter->nic_ops->config_led(adapter, 1, 0xf) == 0) {
143510ee0faeSSucheta Chakraborty 			err = 0;
143610ee0faeSSucheta Chakraborty 			break;
143710ee0faeSSucheta Chakraborty 		}
1438aa43c215SJeff Kirsher 
1439aa43c215SJeff Kirsher 		dev_err(&adapter->pdev->dev,
1440aa43c215SJeff Kirsher 			"Failed to set LED blink state.\n");
1441aa43c215SJeff Kirsher 		break;
1442aa43c215SJeff Kirsher 
1443aa43c215SJeff Kirsher 	case ETHTOOL_ID_INACTIVE:
144410ee0faeSSucheta Chakraborty 		active = 0;
144510ee0faeSSucheta Chakraborty 
144610ee0faeSSucheta Chakraborty 		if (test_bit(__QLCNIC_RESETTING, &adapter->state))
144710ee0faeSSucheta Chakraborty 			break;
144810ee0faeSSucheta Chakraborty 
144910ee0faeSSucheta Chakraborty 		if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
145010ee0faeSSucheta Chakraborty 			if (qlcnic_diag_alloc_res(dev, QLCNIC_LED_TEST))
145110ee0faeSSucheta Chakraborty 				break;
145210ee0faeSSucheta Chakraborty 			set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
145310ee0faeSSucheta Chakraborty 		}
145410ee0faeSSucheta Chakraborty 
1455aa43c215SJeff Kirsher 		if (adapter->nic_ops->config_led(adapter, 0, 0xf))
1456aa43c215SJeff Kirsher 			dev_err(&adapter->pdev->dev,
1457aa43c215SJeff Kirsher 				"Failed to reset LED blink state.\n");
1458aa43c215SJeff Kirsher 
1459aa43c215SJeff Kirsher 		break;
1460aa43c215SJeff Kirsher 
1461aa43c215SJeff Kirsher 	default:
1462aa43c215SJeff Kirsher 		return -EINVAL;
1463aa43c215SJeff Kirsher 	}
1464aa43c215SJeff Kirsher 
146510ee0faeSSucheta Chakraborty 	if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
146634e8c406SHimanshu Madhani 		qlcnic_diag_free_res(dev, drv_sds_rings);
1467aa43c215SJeff Kirsher 
146810ee0faeSSucheta Chakraborty 	if (!active || err)
1469728a98b8SSucheta Chakraborty 		clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
1470728a98b8SSucheta Chakraborty 
147110ee0faeSSucheta Chakraborty 	return err;
1472aa43c215SJeff Kirsher }
1473aa43c215SJeff Kirsher 
1474aa43c215SJeff Kirsher static void
qlcnic_get_wol(struct net_device * dev,struct ethtool_wolinfo * wol)1475aa43c215SJeff Kirsher qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1476aa43c215SJeff Kirsher {
1477aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
1478aa43c215SJeff Kirsher 	u32 wol_cfg;
14794bd8e738SHimanshu Madhani 	int err = 0;
1480aa43c215SJeff Kirsher 
14817e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
14827e38d04bSSony Chacko 		return;
1483aa43c215SJeff Kirsher 	wol->supported = 0;
1484aa43c215SJeff Kirsher 	wol->wolopts = 0;
1485aa43c215SJeff Kirsher 
14864bd8e738SHimanshu Madhani 	wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
14874bd8e738SHimanshu Madhani 	if (err == -EIO)
14884bd8e738SHimanshu Madhani 		return;
1489aa43c215SJeff Kirsher 	if (wol_cfg & (1UL << adapter->portnum))
1490aa43c215SJeff Kirsher 		wol->supported |= WAKE_MAGIC;
1491aa43c215SJeff Kirsher 
14924bd8e738SHimanshu Madhani 	wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
1493aa43c215SJeff Kirsher 	if (wol_cfg & (1UL << adapter->portnum))
1494aa43c215SJeff Kirsher 		wol->wolopts |= WAKE_MAGIC;
1495aa43c215SJeff Kirsher }
1496aa43c215SJeff Kirsher 
1497aa43c215SJeff Kirsher static int
qlcnic_set_wol(struct net_device * dev,struct ethtool_wolinfo * wol)1498aa43c215SJeff Kirsher qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
1499aa43c215SJeff Kirsher {
1500aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(dev);
1501aa43c215SJeff Kirsher 	u32 wol_cfg;
15024bd8e738SHimanshu Madhani 	int err = 0;
1503aa43c215SJeff Kirsher 
15047e38d04bSSony Chacko 	if (qlcnic_83xx_check(adapter))
1505aa43c215SJeff Kirsher 		return -EOPNOTSUPP;
15067e38d04bSSony Chacko 	if (wol->wolopts & ~WAKE_MAGIC)
15077e38d04bSSony Chacko 		return -EINVAL;
1508aa43c215SJeff Kirsher 
15094bd8e738SHimanshu Madhani 	wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV, &err);
15104bd8e738SHimanshu Madhani 	if (err == -EIO)
15114bd8e738SHimanshu Madhani 		return err;
1512aa43c215SJeff Kirsher 	if (!(wol_cfg & (1 << adapter->portnum)))
1513aa43c215SJeff Kirsher 		return -EOPNOTSUPP;
1514aa43c215SJeff Kirsher 
15154bd8e738SHimanshu Madhani 	wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG, &err);
15164bd8e738SHimanshu Madhani 	if (err == -EIO)
15174bd8e738SHimanshu Madhani 		return err;
1518aa43c215SJeff Kirsher 	if (wol->wolopts & WAKE_MAGIC)
1519aa43c215SJeff Kirsher 		wol_cfg |= 1UL << adapter->portnum;
1520aa43c215SJeff Kirsher 	else
1521aa43c215SJeff Kirsher 		wol_cfg &= ~(1UL << adapter->portnum);
1522aa43c215SJeff Kirsher 
1523aa43c215SJeff Kirsher 	QLCWR32(adapter, QLCNIC_WOL_CONFIG, wol_cfg);
1524aa43c215SJeff Kirsher 
1525aa43c215SJeff Kirsher 	return 0;
1526aa43c215SJeff Kirsher }
1527aa43c215SJeff Kirsher 
1528aa43c215SJeff Kirsher /*
1529aa43c215SJeff Kirsher  * Set the coalescing parameters. Currently only normal is supported.
1530aa43c215SJeff Kirsher  * If rx_coalesce_usecs == 0 or rx_max_coalesced_frames == 0 then set the
1531aa43c215SJeff Kirsher  * firmware coalescing to default.
1532aa43c215SJeff Kirsher  */
qlcnic_set_intr_coalesce(struct net_device * netdev,struct ethtool_coalesce * ethcoal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)1533aa43c215SJeff Kirsher static int qlcnic_set_intr_coalesce(struct net_device *netdev,
1534f3ccfda1SYufeng Mo 				    struct ethtool_coalesce *ethcoal,
1535f3ccfda1SYufeng Mo 				    struct kernel_ethtool_coalesce *kernel_coal,
1536f3ccfda1SYufeng Mo 				    struct netlink_ext_ack *extack)
1537aa43c215SJeff Kirsher {
1538aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1539a514722aSHimanshu Madhani 	int err;
1540aa43c215SJeff Kirsher 
1541aa43c215SJeff Kirsher 	if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
1542aa43c215SJeff Kirsher 		return -EINVAL;
1543aa43c215SJeff Kirsher 
1544aa43c215SJeff Kirsher 	/*
1545aa43c215SJeff Kirsher 	* Return Error if unsupported values or
1546aa43c215SJeff Kirsher 	* unsupported parameters are set.
1547aa43c215SJeff Kirsher 	*/
1548aa43c215SJeff Kirsher 	if (ethcoal->rx_coalesce_usecs > 0xffff ||
1549aa43c215SJeff Kirsher 	    ethcoal->rx_max_coalesced_frames > 0xffff ||
1550be273dc1SHimanshu Madhani 	    ethcoal->tx_coalesce_usecs > 0xffff ||
15514a988e31SJakub Kicinski 	    ethcoal->tx_max_coalesced_frames > 0xffff)
1552aa43c215SJeff Kirsher 		return -EINVAL;
1553aa43c215SJeff Kirsher 
1554a514722aSHimanshu Madhani 	err = qlcnic_config_intr_coalesce(adapter, ethcoal);
1555be273dc1SHimanshu Madhani 
1556a514722aSHimanshu Madhani 	return err;
1557aa43c215SJeff Kirsher }
1558aa43c215SJeff Kirsher 
qlcnic_get_intr_coalesce(struct net_device * netdev,struct ethtool_coalesce * ethcoal,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)1559aa43c215SJeff Kirsher static int qlcnic_get_intr_coalesce(struct net_device *netdev,
1560f3ccfda1SYufeng Mo 				    struct ethtool_coalesce *ethcoal,
1561f3ccfda1SYufeng Mo 				    struct kernel_ethtool_coalesce *kernel_coal,
1562f3ccfda1SYufeng Mo 				    struct netlink_ext_ack *extack)
1563aa43c215SJeff Kirsher {
1564aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1565aa43c215SJeff Kirsher 
1566aa43c215SJeff Kirsher 	if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
1567aa43c215SJeff Kirsher 		return -EINVAL;
1568aa43c215SJeff Kirsher 
1569aa43c215SJeff Kirsher 	ethcoal->rx_coalesce_usecs = adapter->ahw->coal.rx_time_us;
1570aa43c215SJeff Kirsher 	ethcoal->rx_max_coalesced_frames = adapter->ahw->coal.rx_packets;
1571be273dc1SHimanshu Madhani 	ethcoal->tx_coalesce_usecs = adapter->ahw->coal.tx_time_us;
1572be273dc1SHimanshu Madhani 	ethcoal->tx_max_coalesced_frames = adapter->ahw->coal.tx_packets;
1573aa43c215SJeff Kirsher 
1574aa43c215SJeff Kirsher 	return 0;
1575aa43c215SJeff Kirsher }
1576aa43c215SJeff Kirsher 
qlcnic_get_msglevel(struct net_device * netdev)1577aa43c215SJeff Kirsher static u32 qlcnic_get_msglevel(struct net_device *netdev)
1578aa43c215SJeff Kirsher {
1579aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1580aa43c215SJeff Kirsher 
158179788450SSony Chacko 	return adapter->ahw->msg_enable;
1582aa43c215SJeff Kirsher }
1583aa43c215SJeff Kirsher 
qlcnic_set_msglevel(struct net_device * netdev,u32 msglvl)1584aa43c215SJeff Kirsher static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
1585aa43c215SJeff Kirsher {
1586aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1587aa43c215SJeff Kirsher 
158879788450SSony Chacko 	adapter->ahw->msg_enable = msglvl;
1589aa43c215SJeff Kirsher }
1590aa43c215SJeff Kirsher 
qlcnic_enable_fw_dump_state(struct qlcnic_adapter * adapter)1591890b6e02SShahed Shaikh int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter)
1592890b6e02SShahed Shaikh {
1593890b6e02SShahed Shaikh 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1594890b6e02SShahed Shaikh 	u32 val;
1595890b6e02SShahed Shaikh 
1596890b6e02SShahed Shaikh 	if (qlcnic_84xx_check(adapter)) {
1597890b6e02SShahed Shaikh 		if (qlcnic_83xx_lock_driver(adapter))
1598890b6e02SShahed Shaikh 			return -EBUSY;
1599890b6e02SShahed Shaikh 
1600890b6e02SShahed Shaikh 		val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1601890b6e02SShahed Shaikh 		val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP;
1602890b6e02SShahed Shaikh 		QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1603890b6e02SShahed Shaikh 
1604890b6e02SShahed Shaikh 		qlcnic_83xx_unlock_driver(adapter);
1605890b6e02SShahed Shaikh 	} else {
1606890b6e02SShahed Shaikh 		fw_dump->enable = true;
1607890b6e02SShahed Shaikh 	}
1608890b6e02SShahed Shaikh 
1609890b6e02SShahed Shaikh 	dev_info(&adapter->pdev->dev, "FW dump enabled\n");
1610890b6e02SShahed Shaikh 
1611890b6e02SShahed Shaikh 	return 0;
1612890b6e02SShahed Shaikh }
1613890b6e02SShahed Shaikh 
qlcnic_disable_fw_dump_state(struct qlcnic_adapter * adapter)1614890b6e02SShahed Shaikh static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter)
1615890b6e02SShahed Shaikh {
1616890b6e02SShahed Shaikh 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1617890b6e02SShahed Shaikh 	u32 val;
1618890b6e02SShahed Shaikh 
1619890b6e02SShahed Shaikh 	if (qlcnic_84xx_check(adapter)) {
1620890b6e02SShahed Shaikh 		if (qlcnic_83xx_lock_driver(adapter))
1621890b6e02SShahed Shaikh 			return -EBUSY;
1622890b6e02SShahed Shaikh 
1623890b6e02SShahed Shaikh 		val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1624890b6e02SShahed Shaikh 		val |= QLC_83XX_IDC_DISABLE_FW_DUMP;
1625890b6e02SShahed Shaikh 		QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val);
1626890b6e02SShahed Shaikh 
1627890b6e02SShahed Shaikh 		qlcnic_83xx_unlock_driver(adapter);
1628890b6e02SShahed Shaikh 	} else {
1629890b6e02SShahed Shaikh 		fw_dump->enable = false;
1630890b6e02SShahed Shaikh 	}
1631890b6e02SShahed Shaikh 
1632890b6e02SShahed Shaikh 	dev_info(&adapter->pdev->dev, "FW dump disabled\n");
1633890b6e02SShahed Shaikh 
1634890b6e02SShahed Shaikh 	return 0;
1635890b6e02SShahed Shaikh }
1636890b6e02SShahed Shaikh 
qlcnic_check_fw_dump_state(struct qlcnic_adapter * adapter)1637890b6e02SShahed Shaikh bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter)
1638890b6e02SShahed Shaikh {
1639890b6e02SShahed Shaikh 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1640890b6e02SShahed Shaikh 	bool state;
1641890b6e02SShahed Shaikh 	u32 val;
1642890b6e02SShahed Shaikh 
1643890b6e02SShahed Shaikh 	if (qlcnic_84xx_check(adapter)) {
1644890b6e02SShahed Shaikh 		val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL);
1645890b6e02SShahed Shaikh 		state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true;
1646890b6e02SShahed Shaikh 	} else {
1647890b6e02SShahed Shaikh 		state = fw_dump->enable;
1648890b6e02SShahed Shaikh 	}
1649890b6e02SShahed Shaikh 
1650890b6e02SShahed Shaikh 	return state;
1651890b6e02SShahed Shaikh }
1652890b6e02SShahed Shaikh 
1653aa43c215SJeff Kirsher static int
qlcnic_get_dump_flag(struct net_device * netdev,struct ethtool_dump * dump)1654aa43c215SJeff Kirsher qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump)
1655aa43c215SJeff Kirsher {
1656aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1657aa43c215SJeff Kirsher 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1658aa43c215SJeff Kirsher 
1659b43e5ee7SSucheta Chakraborty 	if (!fw_dump->tmpl_hdr) {
1660b43e5ee7SSucheta Chakraborty 		netdev_err(adapter->netdev, "FW Dump not supported\n");
1661b43e5ee7SSucheta Chakraborty 		return -ENOTSUPP;
1662b43e5ee7SSucheta Chakraborty 	}
1663b43e5ee7SSucheta Chakraborty 
1664aa43c215SJeff Kirsher 	if (fw_dump->clr)
1665225837a0SShahed Shaikh 		dump->len = fw_dump->tmpl_hdr_size + fw_dump->size;
1666aa43c215SJeff Kirsher 	else
1667aa43c215SJeff Kirsher 		dump->len = 0;
1668bcebe559SManish chopra 
1669890b6e02SShahed Shaikh 	if (!qlcnic_check_fw_dump_state(adapter))
1670bcebe559SManish chopra 		dump->flag = ETH_FW_DUMP_DISABLE;
1671bcebe559SManish chopra 	else
1672225837a0SShahed Shaikh 		dump->flag = fw_dump->cap_mask;
1673bcebe559SManish chopra 
1674aa43c215SJeff Kirsher 	dump->version = adapter->fw_version;
1675aa43c215SJeff Kirsher 	return 0;
1676aa43c215SJeff Kirsher }
1677aa43c215SJeff Kirsher 
1678aa43c215SJeff Kirsher static int
qlcnic_get_dump_data(struct net_device * netdev,struct ethtool_dump * dump,void * buffer)1679aa43c215SJeff Kirsher qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
1680aa43c215SJeff Kirsher 			void *buffer)
1681aa43c215SJeff Kirsher {
1682aa43c215SJeff Kirsher 	int i, copy_sz;
168363507592SShahed Shaikh 	u32 *hdr_ptr;
168463507592SShahed Shaikh 	__le32 *data;
1685aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1686aa43c215SJeff Kirsher 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1687aa43c215SJeff Kirsher 
1688b43e5ee7SSucheta Chakraborty 	if (!fw_dump->tmpl_hdr) {
1689b43e5ee7SSucheta Chakraborty 		netdev_err(netdev, "FW Dump not supported\n");
1690b43e5ee7SSucheta Chakraborty 		return -ENOTSUPP;
1691b43e5ee7SSucheta Chakraborty 	}
1692b43e5ee7SSucheta Chakraborty 
1693aa43c215SJeff Kirsher 	if (!fw_dump->clr) {
1694aa43c215SJeff Kirsher 		netdev_info(netdev, "Dump not available\n");
1695aa43c215SJeff Kirsher 		return -EINVAL;
1696aa43c215SJeff Kirsher 	}
1697225837a0SShahed Shaikh 
1698aa43c215SJeff Kirsher 	/* Copy template header first */
1699225837a0SShahed Shaikh 	copy_sz = fw_dump->tmpl_hdr_size;
1700aa43c215SJeff Kirsher 	hdr_ptr = (u32 *)fw_dump->tmpl_hdr;
1701aa43c215SJeff Kirsher 	data = buffer;
1702aa43c215SJeff Kirsher 	for (i = 0; i < copy_sz/sizeof(u32); i++)
1703aa43c215SJeff Kirsher 		*data++ = cpu_to_le32(*hdr_ptr++);
1704aa43c215SJeff Kirsher 
1705aa43c215SJeff Kirsher 	/* Copy captured dump data */
1706aa43c215SJeff Kirsher 	memcpy(buffer + copy_sz, fw_dump->data, fw_dump->size);
1707aa43c215SJeff Kirsher 	dump->len = copy_sz + fw_dump->size;
1708225837a0SShahed Shaikh 	dump->flag = fw_dump->cap_mask;
1709aa43c215SJeff Kirsher 
1710aa43c215SJeff Kirsher 	/* Free dump area once data has been captured */
1711aa43c215SJeff Kirsher 	vfree(fw_dump->data);
1712aa43c215SJeff Kirsher 	fw_dump->data = NULL;
1713aa43c215SJeff Kirsher 	fw_dump->clr = 0;
1714c47884e4SManish chopra 	netdev_info(netdev, "extracted the FW dump Successfully\n");
1715aa43c215SJeff Kirsher 	return 0;
1716aa43c215SJeff Kirsher }
1717aa43c215SJeff Kirsher 
qlcnic_set_dump_mask(struct qlcnic_adapter * adapter,u32 mask)1718890b6e02SShahed Shaikh static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask)
1719890b6e02SShahed Shaikh {
1720890b6e02SShahed Shaikh 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1721890b6e02SShahed Shaikh 	struct net_device *netdev = adapter->netdev;
1722890b6e02SShahed Shaikh 
1723890b6e02SShahed Shaikh 	if (!qlcnic_check_fw_dump_state(adapter)) {
1724890b6e02SShahed Shaikh 		netdev_info(netdev,
1725890b6e02SShahed Shaikh 			    "Can not change driver mask to 0x%x. FW dump not enabled\n",
1726890b6e02SShahed Shaikh 			    mask);
1727890b6e02SShahed Shaikh 		return -EOPNOTSUPP;
1728890b6e02SShahed Shaikh 	}
1729890b6e02SShahed Shaikh 
1730225837a0SShahed Shaikh 	fw_dump->cap_mask = mask;
1731225837a0SShahed Shaikh 
1732225837a0SShahed Shaikh 	/* Store new capture mask in template header as well*/
1733225837a0SShahed Shaikh 	qlcnic_store_cap_mask(adapter, fw_dump->tmpl_hdr, mask);
1734225837a0SShahed Shaikh 
1735890b6e02SShahed Shaikh 	netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask);
1736890b6e02SShahed Shaikh 	return 0;
1737890b6e02SShahed Shaikh }
1738890b6e02SShahed Shaikh 
1739aa43c215SJeff Kirsher static int
qlcnic_set_dump(struct net_device * netdev,struct ethtool_dump * val)1740aa43c215SJeff Kirsher qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
1741aa43c215SJeff Kirsher {
1742aa43c215SJeff Kirsher 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
1743aa43c215SJeff Kirsher 	struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
1744890b6e02SShahed Shaikh 	bool valid_mask = false;
1745890b6e02SShahed Shaikh 	int i, ret = 0;
1746aa43c215SJeff Kirsher 
1747aa43c215SJeff Kirsher 	switch (val->flag) {
1748aa43c215SJeff Kirsher 	case QLCNIC_FORCE_FW_DUMP_KEY:
1749b43e5ee7SSucheta Chakraborty 		if (!fw_dump->tmpl_hdr) {
1750b43e5ee7SSucheta Chakraborty 			netdev_err(netdev, "FW dump not supported\n");
1751890b6e02SShahed Shaikh 			ret = -EOPNOTSUPP;
1752890b6e02SShahed Shaikh 			break;
1753b43e5ee7SSucheta Chakraborty 		}
1754890b6e02SShahed Shaikh 
1755890b6e02SShahed Shaikh 		if (!qlcnic_check_fw_dump_state(adapter)) {
1756aa43c215SJeff Kirsher 			netdev_info(netdev, "FW dump not enabled\n");
1757890b6e02SShahed Shaikh 			ret = -EOPNOTSUPP;
1758890b6e02SShahed Shaikh 			break;
1759aa43c215SJeff Kirsher 		}
1760890b6e02SShahed Shaikh 
1761aa43c215SJeff Kirsher 		if (fw_dump->clr) {
1762c47884e4SManish chopra 			netdev_info(netdev,
1763aa43c215SJeff Kirsher 				    "Previous dump not cleared, not forcing dump\n");
1764890b6e02SShahed Shaikh 			break;
1765aa43c215SJeff Kirsher 		}
1766890b6e02SShahed Shaikh 
1767aa43c215SJeff Kirsher 		netdev_info(netdev, "Forcing a FW dump\n");
17687e38d04bSSony Chacko 		qlcnic_dev_request_reset(adapter, val->flag);
1769aa43c215SJeff Kirsher 		break;
1770aa43c215SJeff Kirsher 	case QLCNIC_DISABLE_FW_DUMP:
1771890b6e02SShahed Shaikh 		if (!fw_dump->tmpl_hdr) {
1772890b6e02SShahed Shaikh 			netdev_err(netdev, "FW dump not supported\n");
1773890b6e02SShahed Shaikh 			ret = -EOPNOTSUPP;
1774890b6e02SShahed Shaikh 			break;
1775aa43c215SJeff Kirsher 		}
1776890b6e02SShahed Shaikh 
1777890b6e02SShahed Shaikh 		ret = qlcnic_disable_fw_dump_state(adapter);
1778890b6e02SShahed Shaikh 		break;
1779890b6e02SShahed Shaikh 
1780aa43c215SJeff Kirsher 	case QLCNIC_ENABLE_FW_DUMP:
1781b43e5ee7SSucheta Chakraborty 		if (!fw_dump->tmpl_hdr) {
1782b43e5ee7SSucheta Chakraborty 			netdev_err(netdev, "FW dump not supported\n");
1783890b6e02SShahed Shaikh 			ret = -EOPNOTSUPP;
1784890b6e02SShahed Shaikh 			break;
1785b43e5ee7SSucheta Chakraborty 		}
1786890b6e02SShahed Shaikh 
1787890b6e02SShahed Shaikh 		ret = qlcnic_enable_fw_dump_state(adapter);
1788890b6e02SShahed Shaikh 		break;
1789890b6e02SShahed Shaikh 
1790aa43c215SJeff Kirsher 	case QLCNIC_FORCE_FW_RESET:
1791aa43c215SJeff Kirsher 		netdev_info(netdev, "Forcing a FW reset\n");
17927e38d04bSSony Chacko 		qlcnic_dev_request_reset(adapter, val->flag);
1793aa43c215SJeff Kirsher 		adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
1794890b6e02SShahed Shaikh 		break;
17953cc4a678SDan Carpenter 
1796b43e5ee7SSucheta Chakraborty 	case QLCNIC_SET_QUIESCENT:
1797b43e5ee7SSucheta Chakraborty 	case QLCNIC_RESET_QUIESCENT:
179878ea2d97SSucheta Chakraborty 		if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
179978ea2d97SSucheta Chakraborty 			netdev_info(netdev, "Device is in non-operational state\n");
1800890b6e02SShahed Shaikh 		break;
1801890b6e02SShahed Shaikh 
1802aa43c215SJeff Kirsher 	default:
1803b43e5ee7SSucheta Chakraborty 		if (!fw_dump->tmpl_hdr) {
1804b43e5ee7SSucheta Chakraborty 			netdev_err(netdev, "FW dump not supported\n");
1805890b6e02SShahed Shaikh 			ret = -EOPNOTSUPP;
1806890b6e02SShahed Shaikh 			break;
1807b43e5ee7SSucheta Chakraborty 		}
1808890b6e02SShahed Shaikh 
18097e38d04bSSony Chacko 		for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) {
18107e38d04bSSony Chacko 			if (val->flag == qlcnic_fw_dump_level[i]) {
1811890b6e02SShahed Shaikh 				valid_mask = true;
1812890b6e02SShahed Shaikh 				break;
1813aa43c215SJeff Kirsher 			}
18144fbec4d8SManish Chopra 		}
1815890b6e02SShahed Shaikh 
1816890b6e02SShahed Shaikh 		if (valid_mask) {
1817890b6e02SShahed Shaikh 			ret = qlcnic_set_dump_mask(adapter, val->flag);
1818890b6e02SShahed Shaikh 		} else {
1819890b6e02SShahed Shaikh 			netdev_info(netdev, "Invalid dump level: 0x%x\n",
1820890b6e02SShahed Shaikh 				    val->flag);
1821890b6e02SShahed Shaikh 			ret = -EINVAL;
18224fbec4d8SManish Chopra 		}
1823890b6e02SShahed Shaikh 	}
1824890b6e02SShahed Shaikh 	return ret;
1825aa43c215SJeff Kirsher }
1826aa43c215SJeff Kirsher 
1827aa43c215SJeff Kirsher const struct ethtool_ops qlcnic_ethtool_ops = {
18284a988e31SJakub Kicinski 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
18294a988e31SJakub Kicinski 				     ETHTOOL_COALESCE_MAX_FRAMES,
1830aa43c215SJeff Kirsher 	.get_drvinfo = qlcnic_get_drvinfo,
1831aa43c215SJeff Kirsher 	.get_regs_len = qlcnic_get_regs_len,
1832aa43c215SJeff Kirsher 	.get_regs = qlcnic_get_regs,
1833aa43c215SJeff Kirsher 	.get_link = ethtool_op_get_link,
1834aa43c215SJeff Kirsher 	.get_eeprom_len = qlcnic_get_eeprom_len,
1835aa43c215SJeff Kirsher 	.get_eeprom = qlcnic_get_eeprom,
1836aa43c215SJeff Kirsher 	.get_ringparam = qlcnic_get_ringparam,
1837aa43c215SJeff Kirsher 	.set_ringparam = qlcnic_set_ringparam,
1838aa43c215SJeff Kirsher 	.get_channels = qlcnic_get_channels,
1839aa43c215SJeff Kirsher 	.set_channels = qlcnic_set_channels,
1840aa43c215SJeff Kirsher 	.get_pauseparam = qlcnic_get_pauseparam,
1841aa43c215SJeff Kirsher 	.set_pauseparam = qlcnic_set_pauseparam,
1842aa43c215SJeff Kirsher 	.get_wol = qlcnic_get_wol,
1843aa43c215SJeff Kirsher 	.set_wol = qlcnic_set_wol,
1844aa43c215SJeff Kirsher 	.self_test = qlcnic_diag_test,
1845aa43c215SJeff Kirsher 	.get_strings = qlcnic_get_strings,
1846aa43c215SJeff Kirsher 	.get_ethtool_stats = qlcnic_get_ethtool_stats,
1847aa43c215SJeff Kirsher 	.get_sset_count = qlcnic_get_sset_count,
1848aa43c215SJeff Kirsher 	.get_coalesce = qlcnic_get_intr_coalesce,
1849aa43c215SJeff Kirsher 	.set_coalesce = qlcnic_set_intr_coalesce,
1850aa43c215SJeff Kirsher 	.set_phys_id = qlcnic_set_led,
1851aa43c215SJeff Kirsher 	.set_msglevel = qlcnic_set_msglevel,
1852aa43c215SJeff Kirsher 	.get_msglevel = qlcnic_get_msglevel,
1853aa43c215SJeff Kirsher 	.get_dump_flag = qlcnic_get_dump_flag,
1854aa43c215SJeff Kirsher 	.get_dump_data = qlcnic_get_dump_data,
1855aa43c215SJeff Kirsher 	.set_dump = qlcnic_set_dump,
185649cef10fSPhilippe Reynes 	.get_link_ksettings = qlcnic_get_link_ksettings,
185749cef10fSPhilippe Reynes 	.set_link_ksettings = qlcnic_set_link_ksettings,
1858aa43c215SJeff Kirsher };
1859d1a1105eSRajesh Borundia 
1860d1a1105eSRajesh Borundia const struct ethtool_ops qlcnic_sriov_vf_ethtool_ops = {
18614a988e31SJakub Kicinski 	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
18624a988e31SJakub Kicinski 				     ETHTOOL_COALESCE_MAX_FRAMES,
1863d1a1105eSRajesh Borundia 	.get_drvinfo		= qlcnic_get_drvinfo,
1864d1a1105eSRajesh Borundia 	.get_regs_len		= qlcnic_get_regs_len,
1865d1a1105eSRajesh Borundia 	.get_regs		= qlcnic_get_regs,
1866d1a1105eSRajesh Borundia 	.get_link		= ethtool_op_get_link,
1867d1a1105eSRajesh Borundia 	.get_eeprom_len		= qlcnic_get_eeprom_len,
1868d1a1105eSRajesh Borundia 	.get_eeprom		= qlcnic_get_eeprom,
1869d1a1105eSRajesh Borundia 	.get_ringparam		= qlcnic_get_ringparam,
1870d1a1105eSRajesh Borundia 	.set_ringparam		= qlcnic_set_ringparam,
1871d1a1105eSRajesh Borundia 	.get_channels		= qlcnic_get_channels,
1872d1a1105eSRajesh Borundia 	.get_pauseparam		= qlcnic_get_pauseparam,
1873d1a1105eSRajesh Borundia 	.get_wol		= qlcnic_get_wol,
1874d1a1105eSRajesh Borundia 	.get_strings		= qlcnic_get_strings,
1875d1a1105eSRajesh Borundia 	.get_ethtool_stats	= qlcnic_get_ethtool_stats,
1876d1a1105eSRajesh Borundia 	.get_sset_count		= qlcnic_get_sset_count,
1877d1a1105eSRajesh Borundia 	.get_coalesce		= qlcnic_get_intr_coalesce,
1878d1a1105eSRajesh Borundia 	.set_coalesce		= qlcnic_set_intr_coalesce,
1879d1a1105eSRajesh Borundia 	.set_msglevel		= qlcnic_set_msglevel,
1880d1a1105eSRajesh Borundia 	.get_msglevel		= qlcnic_get_msglevel,
188149cef10fSPhilippe Reynes 	.get_link_ksettings	= qlcnic_get_link_ksettings,
1882d1a1105eSRajesh Borundia };
188366451615SSucheta Chakraborty 
188466451615SSucheta Chakraborty const struct ethtool_ops qlcnic_ethtool_failed_ops = {
188566451615SSucheta Chakraborty 	.get_drvinfo		= qlcnic_get_drvinfo,
188666451615SSucheta Chakraborty 	.set_msglevel		= qlcnic_set_msglevel,
188766451615SSucheta Chakraborty 	.get_msglevel		= qlcnic_get_msglevel,
188866451615SSucheta Chakraborty 	.set_dump		= qlcnic_set_dump,
188949cef10fSPhilippe Reynes 	.get_link_ksettings	= qlcnic_get_link_ksettings,
189066451615SSucheta Chakraborty };
1891