1133fac0eSSudarsana Kalluru /* QLogic qede NIC Driver
2133fac0eSSudarsana Kalluru * Copyright (c) 2015 QLogic Corporation
3133fac0eSSudarsana Kalluru *
4133fac0eSSudarsana Kalluru * This software is available under the terms of the GNU General Public License
5133fac0eSSudarsana Kalluru * (GPL) Version 2, available from the file COPYING in the main directory of
6133fac0eSSudarsana Kalluru * this source tree.
7133fac0eSSudarsana Kalluru */
8133fac0eSSudarsana Kalluru 
9133fac0eSSudarsana Kalluru #include <linux/version.h>
10133fac0eSSudarsana Kalluru #include <linux/types.h>
11133fac0eSSudarsana Kalluru #include <linux/netdevice.h>
1216f46bf0SSudarsana Reddy Kalluru #include <linux/etherdevice.h>
13133fac0eSSudarsana Kalluru #include <linux/ethtool.h>
14133fac0eSSudarsana Kalluru #include <linux/string.h>
15133fac0eSSudarsana Kalluru #include <linux/pci.h>
16133fac0eSSudarsana Kalluru #include <linux/capability.h>
17133fac0eSSudarsana Kalluru #include "qede.h"
18133fac0eSSudarsana Kalluru 
19133fac0eSSudarsana Kalluru #define QEDE_STAT_OFFSET(stat_name) (offsetof(struct qede_stats, stat_name))
20133fac0eSSudarsana Kalluru #define QEDE_STAT_STRING(stat_name) (#stat_name)
21133fac0eSSudarsana Kalluru #define _QEDE_STAT(stat_name, pf_only) \
22133fac0eSSudarsana Kalluru 	 {QEDE_STAT_OFFSET(stat_name), QEDE_STAT_STRING(stat_name), pf_only}
23133fac0eSSudarsana Kalluru #define QEDE_PF_STAT(stat_name)		_QEDE_STAT(stat_name, true)
24133fac0eSSudarsana Kalluru #define QEDE_STAT(stat_name)		_QEDE_STAT(stat_name, false)
25133fac0eSSudarsana Kalluru 
26133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \
27133fac0eSSudarsana Kalluru 	 (offsetof(struct qede_rx_queue, stat_name))
28133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name)
29133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \
30133fac0eSSudarsana Kalluru 	 {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)}
3116f46bf0SSudarsana Reddy Kalluru 
3216f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100
3316f46bf0SSudarsana Reddy Kalluru 
34133fac0eSSudarsana Kalluru static const struct {
35133fac0eSSudarsana Kalluru 	u64 offset;
36133fac0eSSudarsana Kalluru 	char string[ETH_GSTRING_LEN];
37133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = {
3868db9ec2SSudarsana Reddy Kalluru 	QEDE_RQSTAT(rcv_pkts),
39133fac0eSSudarsana Kalluru 	QEDE_RQSTAT(rx_hw_errors),
40133fac0eSSudarsana Kalluru 	QEDE_RQSTAT(rx_alloc_errors),
41c72a6125SManish Chopra 	QEDE_RQSTAT(rx_ip_frags),
42133fac0eSSudarsana Kalluru };
43133fac0eSSudarsana Kalluru 
44133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr)
45133fac0eSSudarsana Kalluru #define QEDE_RQSTATS_DATA(dev, sindex, rqindex) \
46133fac0eSSudarsana Kalluru 	(*((u64 *)(((char *)(dev->fp_array[(rqindex)].rxq)) +\
47133fac0eSSudarsana Kalluru 		    qede_rqstats_arr[(sindex)].offset)))
4868db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \
4968db9ec2SSudarsana Reddy Kalluru 	(offsetof(struct qede_tx_queue, stat_name))
5068db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name)
5168db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \
5268db9ec2SSudarsana Reddy Kalluru 	{QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)}
5368db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr)
5468db9ec2SSudarsana Reddy Kalluru static const struct {
5568db9ec2SSudarsana Reddy Kalluru 	u64 offset;
5668db9ec2SSudarsana Reddy Kalluru 	char string[ETH_GSTRING_LEN];
5768db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = {
5868db9ec2SSudarsana Reddy Kalluru 	QEDE_TQSTAT(xmit_pkts),
5968db9ec2SSudarsana Reddy Kalluru 	QEDE_TQSTAT(stopped_cnt),
6068db9ec2SSudarsana Reddy Kalluru };
6168db9ec2SSudarsana Reddy Kalluru 
6268db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTATS_DATA(dev, sindex, tssid, tcid) \
6384fd1b19SArnd Bergmann 	(*((u64 *)(((void *)(&dev->fp_array[tssid].txqs[tcid])) +\
6468db9ec2SSudarsana Reddy Kalluru 		   qede_tqstats_arr[(sindex)].offset)))
6568db9ec2SSudarsana Reddy Kalluru 
66133fac0eSSudarsana Kalluru static const struct {
67133fac0eSSudarsana Kalluru 	u64 offset;
68133fac0eSSudarsana Kalluru 	char string[ETH_GSTRING_LEN];
69133fac0eSSudarsana Kalluru 	bool pf_only;
70133fac0eSSudarsana Kalluru } qede_stats_arr[] = {
71133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_ucast_bytes),
72133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_mcast_bytes),
73133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_bcast_bytes),
74133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_ucast_pkts),
75133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_mcast_pkts),
76133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_bcast_pkts),
77133fac0eSSudarsana Kalluru 
78133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_ucast_bytes),
79133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_mcast_bytes),
80133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_bcast_bytes),
81133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_ucast_pkts),
82133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_mcast_pkts),
83133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_bcast_pkts),
84133fac0eSSudarsana Kalluru 
85133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_64_byte_packets),
86d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_65_to_127_byte_packets),
87d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_128_to_255_byte_packets),
88d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_256_to_511_byte_packets),
89d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_512_to_1023_byte_packets),
90d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_1024_to_1518_byte_packets),
91d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_1519_to_1522_byte_packets),
92d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_1519_to_2047_byte_packets),
93d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_2048_to_4095_byte_packets),
94d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_4096_to_9216_byte_packets),
95d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_9217_to_16383_byte_packets),
96133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_64_byte_packets),
97133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_65_to_127_byte_packets),
98133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_128_to_255_byte_packets),
99133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_256_to_511_byte_packets),
100133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_512_to_1023_byte_packets),
101133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_1024_to_1518_byte_packets),
102133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_1519_to_2047_byte_packets),
103133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_2048_to_4095_byte_packets),
104133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_4096_to_9216_byte_packets),
105133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_9217_to_16383_byte_packets),
106133fac0eSSudarsana Kalluru 
107133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_mac_crtl_frames),
108133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_mac_ctrl_frames),
109133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_pause_frames),
110133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_pause_frames),
111133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_pfc_frames),
112133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_pfc_frames),
113133fac0eSSudarsana Kalluru 
114133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_crc_errors),
115133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_align_errors),
116133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_carrier_errors),
117133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_oversize_packets),
118133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_jabbers),
119133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_undersize_packets),
120133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_fragments),
121133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_lpi_entry_count),
122133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_total_collisions),
123133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(brb_truncates),
124133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(brb_discards),
125133fac0eSSudarsana Kalluru 	QEDE_STAT(no_buff_discards),
126133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(mftag_filter_discards),
127133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(mac_filter_discards),
128133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_err_drop_pkts),
1291a5a366fSSudarsana Reddy Kalluru 	QEDE_STAT(ttl0_discard),
1301a5a366fSSudarsana Reddy Kalluru 	QEDE_STAT(packet_too_big_discard),
131133fac0eSSudarsana Kalluru 
132133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_pkts),
133133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_events),
134133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_aborts_num),
135133fac0eSSudarsana Kalluru 	QEDE_STAT(non_coalesced_pkts),
136133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_bytes),
137133fac0eSSudarsana Kalluru };
138133fac0eSSudarsana Kalluru 
139133fac0eSSudarsana Kalluru #define QEDE_STATS_DATA(dev, index) \
140133fac0eSSudarsana Kalluru 	(*((u64 *)(((char *)(dev)) + offsetof(struct qede_dev, stats) \
141133fac0eSSudarsana Kalluru 			+ qede_stats_arr[(index)].offset)))
142133fac0eSSudarsana Kalluru 
143133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS	ARRAY_SIZE(qede_stats_arr)
144133fac0eSSudarsana Kalluru 
145f3e72109SYuval Mintz enum {
146f3e72109SYuval Mintz 	QEDE_PRI_FLAG_CMT,
147f3e72109SYuval Mintz 	QEDE_PRI_FLAG_LEN,
148f3e72109SYuval Mintz };
149f3e72109SYuval Mintz 
150f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = {
151f3e72109SYuval Mintz 	"Coupled-Function",
152f3e72109SYuval Mintz };
153f3e72109SYuval Mintz 
1543044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests {
15516f46bf0SSudarsana Reddy Kalluru 	QEDE_ETHTOOL_INT_LOOPBACK,
1563044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_INTERRUPT_TEST,
1573044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_MEMORY_TEST,
1583044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_REGISTER_TEST,
1593044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_CLOCK_TEST,
1603044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_TEST_MAX
1613044a02eSSudarsana Reddy Kalluru };
1623044a02eSSudarsana Reddy Kalluru 
1633044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = {
16416f46bf0SSudarsana Reddy Kalluru 	"Internal loopback (offline)",
1653044a02eSSudarsana Reddy Kalluru 	"Interrupt (online)\t",
1663044a02eSSudarsana Reddy Kalluru 	"Memory (online)\t\t",
1673044a02eSSudarsana Reddy Kalluru 	"Register (online)\t",
1683044a02eSSudarsana Reddy Kalluru 	"Clock (online)\t\t",
1693044a02eSSudarsana Reddy Kalluru };
1703044a02eSSudarsana Reddy Kalluru 
171133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
172133fac0eSSudarsana Kalluru {
173133fac0eSSudarsana Kalluru 	int i, j, k;
174133fac0eSSudarsana Kalluru 
1759a4d7e86SSudarsana Reddy Kalluru 	for (i = 0, k = 0; i < QEDE_QUEUE_CNT(edev); i++) {
17668db9ec2SSudarsana Reddy Kalluru 		int tc;
17768db9ec2SSudarsana Reddy Kalluru 
17868db9ec2SSudarsana Reddy Kalluru 		for (j = 0; j < QEDE_NUM_RQSTATS; j++)
17968db9ec2SSudarsana Reddy Kalluru 			sprintf(buf + (k + j) * ETH_GSTRING_LEN,
18068db9ec2SSudarsana Reddy Kalluru 				"%d:   %s", i, qede_rqstats_arr[j].string);
18168db9ec2SSudarsana Reddy Kalluru 		k += QEDE_NUM_RQSTATS;
18268db9ec2SSudarsana Reddy Kalluru 		for (tc = 0; tc < edev->num_tc; tc++) {
18368db9ec2SSudarsana Reddy Kalluru 			for (j = 0; j < QEDE_NUM_TQSTATS; j++)
18468db9ec2SSudarsana Reddy Kalluru 				sprintf(buf + (k + j) * ETH_GSTRING_LEN,
18568db9ec2SSudarsana Reddy Kalluru 					"%d.%d: %s", i, tc,
18668db9ec2SSudarsana Reddy Kalluru 					qede_tqstats_arr[j].string);
18768db9ec2SSudarsana Reddy Kalluru 			k += QEDE_NUM_TQSTATS;
18868db9ec2SSudarsana Reddy Kalluru 		}
18968db9ec2SSudarsana Reddy Kalluru 	}
19068db9ec2SSudarsana Reddy Kalluru 
191133fac0eSSudarsana Kalluru 	for (i = 0, j = 0; i < QEDE_NUM_STATS; i++) {
192fefb0202SYuval Mintz 		if (IS_VF(edev) && qede_stats_arr[i].pf_only)
193fefb0202SYuval Mintz 			continue;
19468db9ec2SSudarsana Reddy Kalluru 		strcpy(buf + (k + j) * ETH_GSTRING_LEN,
195133fac0eSSudarsana Kalluru 		       qede_stats_arr[i].string);
196133fac0eSSudarsana Kalluru 		j++;
197133fac0eSSudarsana Kalluru 	}
198133fac0eSSudarsana Kalluru }
199133fac0eSSudarsana Kalluru 
200133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
201133fac0eSSudarsana Kalluru {
202133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
203133fac0eSSudarsana Kalluru 
204133fac0eSSudarsana Kalluru 	switch (stringset) {
205133fac0eSSudarsana Kalluru 	case ETH_SS_STATS:
206133fac0eSSudarsana Kalluru 		qede_get_strings_stats(edev, buf);
207133fac0eSSudarsana Kalluru 		break;
208f3e72109SYuval Mintz 	case ETH_SS_PRIV_FLAGS:
209f3e72109SYuval Mintz 		memcpy(buf, qede_private_arr,
210f3e72109SYuval Mintz 		       ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN);
211f3e72109SYuval Mintz 		break;
2123044a02eSSudarsana Reddy Kalluru 	case ETH_SS_TEST:
2133044a02eSSudarsana Reddy Kalluru 		memcpy(buf, qede_tests_str_arr,
2143044a02eSSudarsana Reddy Kalluru 		       ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX);
2153044a02eSSudarsana Reddy Kalluru 		break;
216133fac0eSSudarsana Kalluru 	default:
217133fac0eSSudarsana Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
218133fac0eSSudarsana Kalluru 			   "Unsupported stringset 0x%08x\n", stringset);
219133fac0eSSudarsana Kalluru 	}
220133fac0eSSudarsana Kalluru }
221133fac0eSSudarsana Kalluru 
222133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev,
223133fac0eSSudarsana Kalluru 				   struct ethtool_stats *stats, u64 *buf)
224133fac0eSSudarsana Kalluru {
225133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
226133fac0eSSudarsana Kalluru 	int sidx, cnt = 0;
227133fac0eSSudarsana Kalluru 	int qid;
228133fac0eSSudarsana Kalluru 
229133fac0eSSudarsana Kalluru 	qede_fill_by_demand_stats(edev);
230133fac0eSSudarsana Kalluru 
231133fac0eSSudarsana Kalluru 	mutex_lock(&edev->qede_lock);
232133fac0eSSudarsana Kalluru 
2339a4d7e86SSudarsana Reddy Kalluru 	for (qid = 0; qid < QEDE_QUEUE_CNT(edev); qid++) {
23468db9ec2SSudarsana Reddy Kalluru 		int tc;
23568db9ec2SSudarsana Reddy Kalluru 
2369a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[qid].type & QEDE_FASTPATH_RX) {
23768db9ec2SSudarsana Reddy Kalluru 			for (sidx = 0; sidx < QEDE_NUM_RQSTATS; sidx++)
23868db9ec2SSudarsana Reddy Kalluru 				buf[cnt++] = QEDE_RQSTATS_DATA(edev, sidx, qid);
2399a4d7e86SSudarsana Reddy Kalluru 		}
2409a4d7e86SSudarsana Reddy Kalluru 
2419a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[qid].type & QEDE_FASTPATH_TX) {
24268db9ec2SSudarsana Reddy Kalluru 			for (tc = 0; tc < edev->num_tc; tc++) {
24368db9ec2SSudarsana Reddy Kalluru 				for (sidx = 0; sidx < QEDE_NUM_TQSTATS; sidx++)
2449a4d7e86SSudarsana Reddy Kalluru 					buf[cnt++] = QEDE_TQSTATS_DATA(edev,
2459a4d7e86SSudarsana Reddy Kalluru 								       sidx,
2469a4d7e86SSudarsana Reddy Kalluru 								       qid, tc);
2479a4d7e86SSudarsana Reddy Kalluru 			}
24868db9ec2SSudarsana Reddy Kalluru 		}
24968db9ec2SSudarsana Reddy Kalluru 	}
25068db9ec2SSudarsana Reddy Kalluru 
251fefb0202SYuval Mintz 	for (sidx = 0; sidx < QEDE_NUM_STATS; sidx++) {
252fefb0202SYuval Mintz 		if (IS_VF(edev) && qede_stats_arr[sidx].pf_only)
253fefb0202SYuval Mintz 			continue;
254133fac0eSSudarsana Kalluru 		buf[cnt++] = QEDE_STATS_DATA(edev, sidx);
255fefb0202SYuval Mintz 	}
256133fac0eSSudarsana Kalluru 
257133fac0eSSudarsana Kalluru 	mutex_unlock(&edev->qede_lock);
258133fac0eSSudarsana Kalluru }
259133fac0eSSudarsana Kalluru 
260133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset)
261133fac0eSSudarsana Kalluru {
262133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
263133fac0eSSudarsana Kalluru 	int num_stats = QEDE_NUM_STATS;
264133fac0eSSudarsana Kalluru 
265133fac0eSSudarsana Kalluru 	switch (stringset) {
266133fac0eSSudarsana Kalluru 	case ETH_SS_STATS:
267fefb0202SYuval Mintz 		if (IS_VF(edev)) {
268fefb0202SYuval Mintz 			int i;
269fefb0202SYuval Mintz 
270fefb0202SYuval Mintz 			for (i = 0; i < QEDE_NUM_STATS; i++)
271fefb0202SYuval Mintz 				if (qede_stats_arr[i].pf_only)
272fefb0202SYuval Mintz 					num_stats--;
273fefb0202SYuval Mintz 		}
2749a4d7e86SSudarsana Reddy Kalluru 		return num_stats + QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS +
2759a4d7e86SSudarsana Reddy Kalluru 		       QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS * edev->num_tc;
276f3e72109SYuval Mintz 	case ETH_SS_PRIV_FLAGS:
277f3e72109SYuval Mintz 		return QEDE_PRI_FLAG_LEN;
2783044a02eSSudarsana Reddy Kalluru 	case ETH_SS_TEST:
2796ecb0a0cSYuval Mintz 		if (!IS_VF(edev))
2803044a02eSSudarsana Reddy Kalluru 			return QEDE_ETHTOOL_TEST_MAX;
2816ecb0a0cSYuval Mintz 		else
2826ecb0a0cSYuval Mintz 			return 0;
283133fac0eSSudarsana Kalluru 	default:
284133fac0eSSudarsana Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
285133fac0eSSudarsana Kalluru 			   "Unsupported stringset 0x%08x\n", stringset);
286133fac0eSSudarsana Kalluru 		return -EINVAL;
287133fac0eSSudarsana Kalluru 	}
288133fac0eSSudarsana Kalluru }
289133fac0eSSudarsana Kalluru 
290f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev)
291f3e72109SYuval Mintz {
292f3e72109SYuval Mintz 	struct qede_dev *edev = netdev_priv(dev);
293f3e72109SYuval Mintz 
294f3e72109SYuval Mintz 	return (!!(edev->dev_info.common.num_hwfns > 1)) << QEDE_PRI_FLAG_CMT;
295f3e72109SYuval Mintz }
296f3e72109SYuval Mintz 
297054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping {
298054c67d1SSudarsana Reddy Kalluru 	u32 qed_link_mode;
299054c67d1SSudarsana Reddy Kalluru 	u32 ethtool_link_mode;
300054c67d1SSudarsana Reddy Kalluru };
301054c67d1SSudarsana Reddy Kalluru 
302054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = {
303054c67d1SSudarsana Reddy Kalluru 	{QED_LM_FIBRE_BIT, ETHTOOL_LINK_MODE_FIBRE_BIT},
304054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT},
305054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT},
306054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT},
307054c67d1SSudarsana Reddy Kalluru 	{QED_LM_1000baseT_Half_BIT, ETHTOOL_LINK_MODE_1000baseT_Half_BIT},
308054c67d1SSudarsana Reddy Kalluru 	{QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
309054c67d1SSudarsana Reddy Kalluru 	{QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
310054c67d1SSudarsana Reddy Kalluru 	{QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT},
311054c67d1SSudarsana Reddy Kalluru 	{QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT},
312054c67d1SSudarsana Reddy Kalluru 	{QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT},
313054c67d1SSudarsana Reddy Kalluru 	{QED_LM_100000baseKR4_Full_BIT,
314054c67d1SSudarsana Reddy Kalluru 	 ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT},
315054c67d1SSudarsana Reddy Kalluru };
316054c67d1SSudarsana Reddy Kalluru 
317054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name)	\
318054c67d1SSudarsana Reddy Kalluru {								\
319054c67d1SSudarsana Reddy Kalluru 	int i;							\
320054c67d1SSudarsana Reddy Kalluru 								\
321054c67d1SSudarsana Reddy Kalluru 	for (i = 0; i < QED_LM_COUNT; i++) {			\
322054c67d1SSudarsana Reddy Kalluru 		if ((caps) & (qed_lm_map[i].qed_link_mode))	\
323054c67d1SSudarsana Reddy Kalluru 			__set_bit(qed_lm_map[i].ethtool_link_mode,\
324054c67d1SSudarsana Reddy Kalluru 				  lk_ksettings->link_modes.name); \
325054c67d1SSudarsana Reddy Kalluru 	}							\
326054c67d1SSudarsana Reddy Kalluru }
327054c67d1SSudarsana Reddy Kalluru 
328054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name)	\
329054c67d1SSudarsana Reddy Kalluru {								\
330054c67d1SSudarsana Reddy Kalluru 	int i;							\
331054c67d1SSudarsana Reddy Kalluru 								\
332054c67d1SSudarsana Reddy Kalluru 	for (i = 0; i < QED_LM_COUNT; i++) {			\
333054c67d1SSudarsana Reddy Kalluru 		if (test_bit(qed_lm_map[i].ethtool_link_mode,	\
334054c67d1SSudarsana Reddy Kalluru 			     lk_ksettings->link_modes.name))	\
335054c67d1SSudarsana Reddy Kalluru 			caps |= qed_lm_map[i].qed_link_mode;	\
336054c67d1SSudarsana Reddy Kalluru 	}							\
337054c67d1SSudarsana Reddy Kalluru }
338054c67d1SSudarsana Reddy Kalluru 
339054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev,
340054c67d1SSudarsana Reddy Kalluru 				   struct ethtool_link_ksettings *cmd)
341133fac0eSSudarsana Kalluru {
342054c67d1SSudarsana Reddy Kalluru 	struct ethtool_link_settings *base = &cmd->base;
343133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
344133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
345133fac0eSSudarsana Kalluru 
346133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
347133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
348133fac0eSSudarsana Kalluru 
349054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
350054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported)
351054c67d1SSudarsana Reddy Kalluru 
352054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, advertising);
353054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising)
354054c67d1SSudarsana Reddy Kalluru 
355054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
356054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising)
357054c67d1SSudarsana Reddy Kalluru 
358133fac0eSSudarsana Kalluru 	if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) {
359054c67d1SSudarsana Reddy Kalluru 		base->speed = current_link.speed;
360054c67d1SSudarsana Reddy Kalluru 		base->duplex = current_link.duplex;
361133fac0eSSudarsana Kalluru 	} else {
362054c67d1SSudarsana Reddy Kalluru 		base->speed = SPEED_UNKNOWN;
363054c67d1SSudarsana Reddy Kalluru 		base->duplex = DUPLEX_UNKNOWN;
364133fac0eSSudarsana Kalluru 	}
365054c67d1SSudarsana Reddy Kalluru 	base->port = current_link.port;
366054c67d1SSudarsana Reddy Kalluru 	base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE :
367133fac0eSSudarsana Kalluru 			AUTONEG_DISABLE;
368133fac0eSSudarsana Kalluru 
369133fac0eSSudarsana Kalluru 	return 0;
370133fac0eSSudarsana Kalluru }
371133fac0eSSudarsana Kalluru 
372054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev,
373054c67d1SSudarsana Reddy Kalluru 				   const struct ethtool_link_ksettings *cmd)
374133fac0eSSudarsana Kalluru {
375054c67d1SSudarsana Reddy Kalluru 	const struct ethtool_link_settings *base = &cmd->base;
376133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
377133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
378133fac0eSSudarsana Kalluru 	struct qed_link_params params;
379133fac0eSSudarsana Kalluru 
380fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
381054c67d1SSudarsana Reddy Kalluru 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
382133fac0eSSudarsana Kalluru 		return -EOPNOTSUPP;
383133fac0eSSudarsana Kalluru 	}
384133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
385133fac0eSSudarsana Kalluru 	memset(&params, 0, sizeof(params));
386133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
387133fac0eSSudarsana Kalluru 
388133fac0eSSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS;
389133fac0eSSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG;
390054c67d1SSudarsana Reddy Kalluru 	if (base->autoneg == AUTONEG_ENABLE) {
391133fac0eSSudarsana Kalluru 		params.autoneg = true;
392133fac0eSSudarsana Kalluru 		params.forced_speed = 0;
393054c67d1SSudarsana Reddy Kalluru 		QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising)
394133fac0eSSudarsana Kalluru 	} else {		/* forced speed */
395133fac0eSSudarsana Kalluru 		params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED;
396133fac0eSSudarsana Kalluru 		params.autoneg = false;
397054c67d1SSudarsana Reddy Kalluru 		params.forced_speed = base->speed;
398054c67d1SSudarsana Reddy Kalluru 		switch (base->speed) {
399133fac0eSSudarsana Kalluru 		case SPEED_10000:
400133fac0eSSudarsana Kalluru 			if (!(current_link.supported_caps &
401054c67d1SSudarsana Reddy Kalluru 			      QED_LM_10000baseKR_Full_BIT)) {
402133fac0eSSudarsana Kalluru 				DP_INFO(edev, "10G speed not supported\n");
403133fac0eSSudarsana Kalluru 				return -EINVAL;
404133fac0eSSudarsana Kalluru 			}
405054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_10000baseKR_Full_BIT;
406054c67d1SSudarsana Reddy Kalluru 			break;
407054c67d1SSudarsana Reddy Kalluru 		case SPEED_25000:
408054c67d1SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
409054c67d1SSudarsana Reddy Kalluru 			      QED_LM_25000baseKR_Full_BIT)) {
410054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "25G speed not supported\n");
411054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
412054c67d1SSudarsana Reddy Kalluru 			}
413054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_25000baseKR_Full_BIT;
414133fac0eSSudarsana Kalluru 			break;
415133fac0eSSudarsana Kalluru 		case SPEED_40000:
416133fac0eSSudarsana Kalluru 			if (!(current_link.supported_caps &
417054c67d1SSudarsana Reddy Kalluru 			      QED_LM_40000baseLR4_Full_BIT)) {
418133fac0eSSudarsana Kalluru 				DP_INFO(edev, "40G speed not supported\n");
419133fac0eSSudarsana Kalluru 				return -EINVAL;
420133fac0eSSudarsana Kalluru 			}
421054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_40000baseLR4_Full_BIT;
422054c67d1SSudarsana Reddy Kalluru 			break;
42316d5946aSYuval Mintz 		case SPEED_50000:
424054c67d1SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
425054c67d1SSudarsana Reddy Kalluru 			      QED_LM_50000baseKR2_Full_BIT)) {
426054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "50G speed not supported\n");
427054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
428054c67d1SSudarsana Reddy Kalluru 			}
429054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_50000baseKR2_Full_BIT;
430054c67d1SSudarsana Reddy Kalluru 			break;
43116d5946aSYuval Mintz 		case SPEED_100000:
432054c67d1SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
433054c67d1SSudarsana Reddy Kalluru 			      QED_LM_100000baseKR4_Full_BIT)) {
434054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "100G speed not supported\n");
435054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
436054c67d1SSudarsana Reddy Kalluru 			}
437054c67d1SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_100000baseKR4_Full_BIT;
438133fac0eSSudarsana Kalluru 			break;
439133fac0eSSudarsana Kalluru 		default:
440054c67d1SSudarsana Reddy Kalluru 			DP_INFO(edev, "Unsupported speed %u\n", base->speed);
441133fac0eSSudarsana Kalluru 			return -EINVAL;
442133fac0eSSudarsana Kalluru 		}
443133fac0eSSudarsana Kalluru 	}
444133fac0eSSudarsana Kalluru 
445133fac0eSSudarsana Kalluru 	params.link_up = true;
446133fac0eSSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
447133fac0eSSudarsana Kalluru 
448133fac0eSSudarsana Kalluru 	return 0;
449133fac0eSSudarsana Kalluru }
450133fac0eSSudarsana Kalluru 
451133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev,
452133fac0eSSudarsana Kalluru 			     struct ethtool_drvinfo *info)
453133fac0eSSudarsana Kalluru {
454133fac0eSSudarsana Kalluru 	char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN];
455133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
456133fac0eSSudarsana Kalluru 
457133fac0eSSudarsana Kalluru 	strlcpy(info->driver, "qede", sizeof(info->driver));
458133fac0eSSudarsana Kalluru 	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
459133fac0eSSudarsana Kalluru 
460133fac0eSSudarsana Kalluru 	snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
461133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_major,
462133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_minor,
463133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_rev,
464133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_eng);
465133fac0eSSudarsana Kalluru 
466133fac0eSSudarsana Kalluru 	snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
467133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 24) & 0xFF,
468133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 16) & 0xFF,
469133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 8) & 0xFF,
470133fac0eSSudarsana Kalluru 		 edev->dev_info.common.mfw_rev & 0xFF);
471133fac0eSSudarsana Kalluru 
472133fac0eSSudarsana Kalluru 	if ((strlen(storm) + strlen(mfw) + strlen("mfw storm  ")) <
473133fac0eSSudarsana Kalluru 	    sizeof(info->fw_version)) {
474133fac0eSSudarsana Kalluru 		snprintf(info->fw_version, sizeof(info->fw_version),
475133fac0eSSudarsana Kalluru 			 "mfw %s storm %s", mfw, storm);
476133fac0eSSudarsana Kalluru 	} else {
477133fac0eSSudarsana Kalluru 		snprintf(info->fw_version, sizeof(info->fw_version),
478133fac0eSSudarsana Kalluru 			 "%s %s", mfw, storm);
479133fac0eSSudarsana Kalluru 	}
480133fac0eSSudarsana Kalluru 
481133fac0eSSudarsana Kalluru 	strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
482133fac0eSSudarsana Kalluru }
483133fac0eSSudarsana Kalluru 
484133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev)
485133fac0eSSudarsana Kalluru {
486133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
487133fac0eSSudarsana Kalluru 
4881a635e48SYuval Mintz 	return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module;
489133fac0eSSudarsana Kalluru }
490133fac0eSSudarsana Kalluru 
491133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level)
492133fac0eSSudarsana Kalluru {
493133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
494133fac0eSSudarsana Kalluru 	u32 dp_module = 0;
495133fac0eSSudarsana Kalluru 	u8 dp_level = 0;
496133fac0eSSudarsana Kalluru 
497133fac0eSSudarsana Kalluru 	qede_config_debug(level, &dp_module, &dp_level);
498133fac0eSSudarsana Kalluru 
499133fac0eSSudarsana Kalluru 	edev->dp_level = dp_level;
500133fac0eSSudarsana Kalluru 	edev->dp_module = dp_module;
501133fac0eSSudarsana Kalluru 	edev->ops->common->update_msglvl(edev->cdev,
502133fac0eSSudarsana Kalluru 					 dp_module, dp_level);
503133fac0eSSudarsana Kalluru }
504133fac0eSSudarsana Kalluru 
50532a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev)
50632a7a570SSudarsana Kalluru {
50732a7a570SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
50832a7a570SSudarsana Kalluru 	struct qed_link_output current_link;
50932a7a570SSudarsana Kalluru 	struct qed_link_params link_params;
51032a7a570SSudarsana Kalluru 
511fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
5121a635e48SYuval Mintz 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
513fe7cd2bfSYuval Mintz 		return -EOPNOTSUPP;
514fe7cd2bfSYuval Mintz 	}
515fe7cd2bfSYuval Mintz 
51632a7a570SSudarsana Kalluru 	if (!netif_running(dev))
51732a7a570SSudarsana Kalluru 		return 0;
51832a7a570SSudarsana Kalluru 
51932a7a570SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
52032a7a570SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
52132a7a570SSudarsana Kalluru 	if (!current_link.link_up)
52232a7a570SSudarsana Kalluru 		return 0;
52332a7a570SSudarsana Kalluru 
52432a7a570SSudarsana Kalluru 	/* Toggle the link */
52532a7a570SSudarsana Kalluru 	memset(&link_params, 0, sizeof(link_params));
52632a7a570SSudarsana Kalluru 	link_params.link_up = false;
52732a7a570SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
52832a7a570SSudarsana Kalluru 	link_params.link_up = true;
52932a7a570SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
53032a7a570SSudarsana Kalluru 
53132a7a570SSudarsana Kalluru 	return 0;
53232a7a570SSudarsana Kalluru }
53332a7a570SSudarsana Kalluru 
534133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev)
535133fac0eSSudarsana Kalluru {
536133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
537133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
538133fac0eSSudarsana Kalluru 
539133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
540133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
541133fac0eSSudarsana Kalluru 
542133fac0eSSudarsana Kalluru 	return current_link.link_up;
543133fac0eSSudarsana Kalluru }
544133fac0eSSudarsana Kalluru 
545d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev,
546d552fa84SSudarsana Reddy Kalluru 			     struct ethtool_coalesce *coal)
547d552fa84SSudarsana Reddy Kalluru {
548d552fa84SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
549d2890deaSSudarsana Reddy Kalluru 	u16 rxc, txc;
550d552fa84SSudarsana Reddy Kalluru 
551d552fa84SSudarsana Reddy Kalluru 	memset(coal, 0, sizeof(struct ethtool_coalesce));
552d2890deaSSudarsana Reddy Kalluru 	edev->ops->common->get_coalesce(edev->cdev, &rxc, &txc);
553d2890deaSSudarsana Reddy Kalluru 
554d2890deaSSudarsana Reddy Kalluru 	coal->rx_coalesce_usecs = rxc;
555d2890deaSSudarsana Reddy Kalluru 	coal->tx_coalesce_usecs = txc;
556d552fa84SSudarsana Reddy Kalluru 
557d552fa84SSudarsana Reddy Kalluru 	return 0;
558d552fa84SSudarsana Reddy Kalluru }
559d552fa84SSudarsana Reddy Kalluru 
560d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev,
561d552fa84SSudarsana Reddy Kalluru 			     struct ethtool_coalesce *coal)
562d552fa84SSudarsana Reddy Kalluru {
563d552fa84SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
564d552fa84SSudarsana Reddy Kalluru 	int i, rc = 0;
565d552fa84SSudarsana Reddy Kalluru 	u16 rxc, txc;
566d552fa84SSudarsana Reddy Kalluru 	u8 sb_id;
567d552fa84SSudarsana Reddy Kalluru 
568d552fa84SSudarsana Reddy Kalluru 	if (!netif_running(dev)) {
569d552fa84SSudarsana Reddy Kalluru 		DP_INFO(edev, "Interface is down\n");
570d552fa84SSudarsana Reddy Kalluru 		return -EINVAL;
571d552fa84SSudarsana Reddy Kalluru 	}
572d552fa84SSudarsana Reddy Kalluru 
573d552fa84SSudarsana Reddy Kalluru 	if (coal->rx_coalesce_usecs > QED_COALESCE_MAX ||
574d552fa84SSudarsana Reddy Kalluru 	    coal->tx_coalesce_usecs > QED_COALESCE_MAX) {
575d552fa84SSudarsana Reddy Kalluru 		DP_INFO(edev,
576d552fa84SSudarsana Reddy Kalluru 			"Can't support requested %s coalesce value [max supported value %d]\n",
577d552fa84SSudarsana Reddy Kalluru 			coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx"
578d552fa84SSudarsana Reddy Kalluru 								   : "tx",
579d552fa84SSudarsana Reddy Kalluru 			QED_COALESCE_MAX);
580d552fa84SSudarsana Reddy Kalluru 		return -EINVAL;
581d552fa84SSudarsana Reddy Kalluru 	}
582d552fa84SSudarsana Reddy Kalluru 
583d552fa84SSudarsana Reddy Kalluru 	rxc = (u16)coal->rx_coalesce_usecs;
584d552fa84SSudarsana Reddy Kalluru 	txc = (u16)coal->tx_coalesce_usecs;
5859a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
586d552fa84SSudarsana Reddy Kalluru 		sb_id = edev->fp_array[i].sb_info->igu_sb_id;
587d552fa84SSudarsana Reddy Kalluru 		rc = edev->ops->common->set_coalesce(edev->cdev, rxc, txc,
588d552fa84SSudarsana Reddy Kalluru 						     (u8)i, sb_id);
589d552fa84SSudarsana Reddy Kalluru 		if (rc) {
590d552fa84SSudarsana Reddy Kalluru 			DP_INFO(edev, "Set coalesce error, rc = %d\n", rc);
591d552fa84SSudarsana Reddy Kalluru 			return rc;
592d552fa84SSudarsana Reddy Kalluru 		}
593d552fa84SSudarsana Reddy Kalluru 	}
594d552fa84SSudarsana Reddy Kalluru 
595d552fa84SSudarsana Reddy Kalluru 	return rc;
596d552fa84SSudarsana Reddy Kalluru }
597d552fa84SSudarsana Reddy Kalluru 
59801ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev,
59901ef7e05SSudarsana Kalluru 			       struct ethtool_ringparam *ering)
60001ef7e05SSudarsana Kalluru {
60101ef7e05SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
60201ef7e05SSudarsana Kalluru 
60301ef7e05SSudarsana Kalluru 	ering->rx_max_pending = NUM_RX_BDS_MAX;
60401ef7e05SSudarsana Kalluru 	ering->rx_pending = edev->q_num_rx_buffers;
60501ef7e05SSudarsana Kalluru 	ering->tx_max_pending = NUM_TX_BDS_MAX;
60601ef7e05SSudarsana Kalluru 	ering->tx_pending = edev->q_num_tx_buffers;
60701ef7e05SSudarsana Kalluru }
60801ef7e05SSudarsana Kalluru 
60901ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev,
61001ef7e05SSudarsana Kalluru 			      struct ethtool_ringparam *ering)
61101ef7e05SSudarsana Kalluru {
61201ef7e05SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
61301ef7e05SSudarsana Kalluru 
61401ef7e05SSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
61501ef7e05SSudarsana Kalluru 		   "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n",
61601ef7e05SSudarsana Kalluru 		   ering->rx_pending, ering->tx_pending);
61701ef7e05SSudarsana Kalluru 
61801ef7e05SSudarsana Kalluru 	/* Validate legality of configuration */
61901ef7e05SSudarsana Kalluru 	if (ering->rx_pending > NUM_RX_BDS_MAX ||
62001ef7e05SSudarsana Kalluru 	    ering->rx_pending < NUM_RX_BDS_MIN ||
62101ef7e05SSudarsana Kalluru 	    ering->tx_pending > NUM_TX_BDS_MAX ||
62201ef7e05SSudarsana Kalluru 	    ering->tx_pending < NUM_TX_BDS_MIN) {
62301ef7e05SSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
62401ef7e05SSudarsana Kalluru 			   "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n",
62501ef7e05SSudarsana Kalluru 			   NUM_RX_BDS_MIN, NUM_RX_BDS_MAX,
62601ef7e05SSudarsana Kalluru 			   NUM_TX_BDS_MIN, NUM_TX_BDS_MAX);
62701ef7e05SSudarsana Kalluru 		return -EINVAL;
62801ef7e05SSudarsana Kalluru 	}
62901ef7e05SSudarsana Kalluru 
63001ef7e05SSudarsana Kalluru 	/* Change ring size and re-load */
63101ef7e05SSudarsana Kalluru 	edev->q_num_rx_buffers = ering->rx_pending;
63201ef7e05SSudarsana Kalluru 	edev->q_num_tx_buffers = ering->tx_pending;
63301ef7e05SSudarsana Kalluru 
63401ef7e05SSudarsana Kalluru 	if (netif_running(edev->ndev))
63501ef7e05SSudarsana Kalluru 		qede_reload(edev, NULL, NULL);
63601ef7e05SSudarsana Kalluru 
63701ef7e05SSudarsana Kalluru 	return 0;
63801ef7e05SSudarsana Kalluru }
63901ef7e05SSudarsana Kalluru 
6400f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev,
6410f7db144SSudarsana Kalluru 				struct ethtool_pauseparam *epause)
6420f7db144SSudarsana Kalluru {
6430f7db144SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
6440f7db144SSudarsana Kalluru 	struct qed_link_output current_link;
6450f7db144SSudarsana Kalluru 
6460f7db144SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
6470f7db144SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
6480f7db144SSudarsana Kalluru 
6490f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE)
6500f7db144SSudarsana Kalluru 		epause->autoneg = true;
6510f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE)
6520f7db144SSudarsana Kalluru 		epause->rx_pause = true;
6530f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE)
6540f7db144SSudarsana Kalluru 		epause->tx_pause = true;
6550f7db144SSudarsana Kalluru 
6560f7db144SSudarsana Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
6570f7db144SSudarsana Kalluru 		   "ethtool_pauseparam: cmd %d  autoneg %d  rx_pause %d  tx_pause %d\n",
6580f7db144SSudarsana Kalluru 		   epause->cmd, epause->autoneg, epause->rx_pause,
6590f7db144SSudarsana Kalluru 		   epause->tx_pause);
6600f7db144SSudarsana Kalluru }
6610f7db144SSudarsana Kalluru 
6620f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev,
6630f7db144SSudarsana Kalluru 			       struct ethtool_pauseparam *epause)
6640f7db144SSudarsana Kalluru {
6650f7db144SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
6660f7db144SSudarsana Kalluru 	struct qed_link_params params;
6670f7db144SSudarsana Kalluru 	struct qed_link_output current_link;
6680f7db144SSudarsana Kalluru 
669fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
6700f7db144SSudarsana Kalluru 		DP_INFO(edev,
671fe7cd2bfSYuval Mintz 			"Pause settings are not allowed to be changed\n");
6720f7db144SSudarsana Kalluru 		return -EOPNOTSUPP;
6730f7db144SSudarsana Kalluru 	}
6740f7db144SSudarsana Kalluru 
6750f7db144SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
6760f7db144SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
6770f7db144SSudarsana Kalluru 
6780f7db144SSudarsana Kalluru 	memset(&params, 0, sizeof(params));
6790f7db144SSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG;
6800f7db144SSudarsana Kalluru 	if (epause->autoneg) {
681d194fd26SYuval Mintz 		if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) {
6820f7db144SSudarsana Kalluru 			DP_INFO(edev, "autoneg not supported\n");
6830f7db144SSudarsana Kalluru 			return -EINVAL;
6840f7db144SSudarsana Kalluru 		}
6850f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
6860f7db144SSudarsana Kalluru 	}
6870f7db144SSudarsana Kalluru 	if (epause->rx_pause)
6880f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_RX_ENABLE;
6890f7db144SSudarsana Kalluru 	if (epause->tx_pause)
6900f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_TX_ENABLE;
6910f7db144SSudarsana Kalluru 
6920f7db144SSudarsana Kalluru 	params.link_up = true;
6930f7db144SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
6940f7db144SSudarsana Kalluru 
6950f7db144SSudarsana Kalluru 	return 0;
6960f7db144SSudarsana Kalluru }
6970f7db144SSudarsana Kalluru 
698e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev,
699e0971c83STomer Tayar 			  struct ethtool_regs *regs, void *buffer)
700e0971c83STomer Tayar {
701e0971c83STomer Tayar 	struct qede_dev *edev = netdev_priv(ndev);
702e0971c83STomer Tayar 
703e0971c83STomer Tayar 	regs->version = 0;
704e0971c83STomer Tayar 	memset(buffer, 0, regs->len);
705e0971c83STomer Tayar 
706e0971c83STomer Tayar 	if (edev->ops && edev->ops->common)
707e0971c83STomer Tayar 		edev->ops->common->dbg_all_data(edev->cdev, buffer);
708e0971c83STomer Tayar }
709e0971c83STomer Tayar 
710e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev)
711e0971c83STomer Tayar {
712e0971c83STomer Tayar 	struct qede_dev *edev = netdev_priv(ndev);
713e0971c83STomer Tayar 
714e0971c83STomer Tayar 	if (edev->ops && edev->ops->common)
715e0971c83STomer Tayar 		return edev->ops->common->dbg_all_data_size(edev->cdev);
716e0971c83STomer Tayar 	else
717e0971c83STomer Tayar 		return -EINVAL;
718e0971c83STomer Tayar }
719e0971c83STomer Tayar 
720133fac0eSSudarsana Kalluru static void qede_update_mtu(struct qede_dev *edev, union qede_reload_args *args)
721133fac0eSSudarsana Kalluru {
722133fac0eSSudarsana Kalluru 	edev->ndev->mtu = args->mtu;
723133fac0eSSudarsana Kalluru }
724133fac0eSSudarsana Kalluru 
725133fac0eSSudarsana Kalluru /* Netdevice NDOs */
726133fac0eSSudarsana Kalluru #define ETH_MAX_JUMBO_PACKET_SIZE	9600
727133fac0eSSudarsana Kalluru #define ETH_MIN_PACKET_SIZE		60
728133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu)
729133fac0eSSudarsana Kalluru {
730133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
731133fac0eSSudarsana Kalluru 	union qede_reload_args args;
732133fac0eSSudarsana Kalluru 
733133fac0eSSudarsana Kalluru 	if ((new_mtu > ETH_MAX_JUMBO_PACKET_SIZE) ||
734133fac0eSSudarsana Kalluru 	    ((new_mtu + ETH_HLEN) < ETH_MIN_PACKET_SIZE)) {
735133fac0eSSudarsana Kalluru 		DP_ERR(edev, "Can't support requested MTU size\n");
736133fac0eSSudarsana Kalluru 		return -EINVAL;
737133fac0eSSudarsana Kalluru 	}
738133fac0eSSudarsana Kalluru 
739133fac0eSSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
740133fac0eSSudarsana Kalluru 		   "Configuring MTU size of %d\n", new_mtu);
741133fac0eSSudarsana Kalluru 
742133fac0eSSudarsana Kalluru 	/* Set the mtu field and re-start the interface if needed*/
743133fac0eSSudarsana Kalluru 	args.mtu = new_mtu;
744133fac0eSSudarsana Kalluru 
745133fac0eSSudarsana Kalluru 	if (netif_running(edev->ndev))
746133fac0eSSudarsana Kalluru 		qede_reload(edev, &qede_update_mtu, &args);
747133fac0eSSudarsana Kalluru 
748133fac0eSSudarsana Kalluru 	qede_update_mtu(edev, &args);
749133fac0eSSudarsana Kalluru 
750133fac0eSSudarsana Kalluru 	return 0;
751133fac0eSSudarsana Kalluru }
752133fac0eSSudarsana Kalluru 
7538edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev,
7548edf049dSSudarsana Kalluru 			      struct ethtool_channels *channels)
7558edf049dSSudarsana Kalluru {
7568edf049dSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
7578edf049dSSudarsana Kalluru 
7588edf049dSSudarsana Kalluru 	channels->max_combined = QEDE_MAX_RSS_CNT(edev);
759bdc8cbd3SSudarsana Reddy Kalluru 	channels->max_rx = QEDE_MAX_RSS_CNT(edev);
760bdc8cbd3SSudarsana Reddy Kalluru 	channels->max_tx = QEDE_MAX_RSS_CNT(edev);
7619a4d7e86SSudarsana Reddy Kalluru 	channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx -
7629a4d7e86SSudarsana Reddy Kalluru 					edev->fp_num_rx;
7639a4d7e86SSudarsana Reddy Kalluru 	channels->tx_count = edev->fp_num_tx;
7649a4d7e86SSudarsana Reddy Kalluru 	channels->rx_count = edev->fp_num_rx;
7658edf049dSSudarsana Kalluru }
7668edf049dSSudarsana Kalluru 
7678edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev,
7688edf049dSSudarsana Kalluru 			     struct ethtool_channels *channels)
7698edf049dSSudarsana Kalluru {
7708edf049dSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
7719a4d7e86SSudarsana Reddy Kalluru 	u32 count;
7728edf049dSSudarsana Kalluru 
7738edf049dSSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
7748edf049dSSudarsana Kalluru 		   "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n",
7758edf049dSSudarsana Kalluru 		   channels->rx_count, channels->tx_count,
7768edf049dSSudarsana Kalluru 		   channels->other_count, channels->combined_count);
7778edf049dSSudarsana Kalluru 
7789a4d7e86SSudarsana Reddy Kalluru 	count = channels->rx_count + channels->tx_count +
7799a4d7e86SSudarsana Reddy Kalluru 			channels->combined_count;
7809a4d7e86SSudarsana Reddy Kalluru 
7819a4d7e86SSudarsana Reddy Kalluru 	/* We don't support `other' channels */
7829a4d7e86SSudarsana Reddy Kalluru 	if (channels->other_count) {
7838edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
7848edf049dSSudarsana Kalluru 			   "command parameters not supported\n");
7858edf049dSSudarsana Kalluru 		return -EINVAL;
7868edf049dSSudarsana Kalluru 	}
7878edf049dSSudarsana Kalluru 
7889a4d7e86SSudarsana Reddy Kalluru 	if (!(channels->combined_count || (channels->rx_count &&
7899a4d7e86SSudarsana Reddy Kalluru 					   channels->tx_count))) {
7909a4d7e86SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
7919a4d7e86SSudarsana Reddy Kalluru 			   "need to request at least one transmit and one receive channel\n");
7929a4d7e86SSudarsana Reddy Kalluru 		return -EINVAL;
7939a4d7e86SSudarsana Reddy Kalluru 	}
7949a4d7e86SSudarsana Reddy Kalluru 
7959a4d7e86SSudarsana Reddy Kalluru 	if (count > QEDE_MAX_RSS_CNT(edev)) {
7969a4d7e86SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
7979a4d7e86SSudarsana Reddy Kalluru 			   "requested channels = %d max supported channels = %d\n",
7989a4d7e86SSudarsana Reddy Kalluru 			   count, QEDE_MAX_RSS_CNT(edev));
7999a4d7e86SSudarsana Reddy Kalluru 		return -EINVAL;
8009a4d7e86SSudarsana Reddy Kalluru 	}
8019a4d7e86SSudarsana Reddy Kalluru 
8028edf049dSSudarsana Kalluru 	/* Check if there was a change in the active parameters */
8039a4d7e86SSudarsana Reddy Kalluru 	if ((count == QEDE_QUEUE_CNT(edev)) &&
8049a4d7e86SSudarsana Reddy Kalluru 	    (channels->tx_count == edev->fp_num_tx) &&
8059a4d7e86SSudarsana Reddy Kalluru 	    (channels->rx_count == edev->fp_num_rx)) {
8068edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
8078edf049dSSudarsana Kalluru 			   "No change in active parameters\n");
8088edf049dSSudarsana Kalluru 		return 0;
8098edf049dSSudarsana Kalluru 	}
8108edf049dSSudarsana Kalluru 
8118edf049dSSudarsana Kalluru 	/* We need the number of queues to be divisible between the hwfns */
8129a4d7e86SSudarsana Reddy Kalluru 	if ((count % edev->dev_info.common.num_hwfns) ||
8139a4d7e86SSudarsana Reddy Kalluru 	    (channels->tx_count % edev->dev_info.common.num_hwfns) ||
8149a4d7e86SSudarsana Reddy Kalluru 	    (channels->rx_count % edev->dev_info.common.num_hwfns)) {
8158edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
8169a4d7e86SSudarsana Reddy Kalluru 			   "Number of channels must be divisible by %04x\n",
8178edf049dSSudarsana Kalluru 			   edev->dev_info.common.num_hwfns);
8188edf049dSSudarsana Kalluru 		return -EINVAL;
8198edf049dSSudarsana Kalluru 	}
8208edf049dSSudarsana Kalluru 
8218edf049dSSudarsana Kalluru 	/* Set number of queues and reload if necessary */
8229a4d7e86SSudarsana Reddy Kalluru 	edev->req_queues = count;
8239a4d7e86SSudarsana Reddy Kalluru 	edev->req_num_tx = channels->tx_count;
8249a4d7e86SSudarsana Reddy Kalluru 	edev->req_num_rx = channels->rx_count;
825ed0dd915SSudarsana Reddy Kalluru 	/* Reset the indirection table if rx queue count is updated */
826ed0dd915SSudarsana Reddy Kalluru 	if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) {
827ed0dd915SSudarsana Reddy Kalluru 		edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED;
828ed0dd915SSudarsana Reddy Kalluru 		memset(&edev->rss_params.rss_ind_table, 0,
829ed0dd915SSudarsana Reddy Kalluru 		       sizeof(edev->rss_params.rss_ind_table));
830ed0dd915SSudarsana Reddy Kalluru 	}
831ed0dd915SSudarsana Reddy Kalluru 
8328edf049dSSudarsana Kalluru 	if (netif_running(dev))
8338edf049dSSudarsana Kalluru 		qede_reload(edev, NULL, NULL);
8348edf049dSSudarsana Kalluru 
8358edf049dSSudarsana Kalluru 	return 0;
8368edf049dSSudarsana Kalluru }
8378edf049dSSudarsana Kalluru 
8383d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev,
8393d971cbdSSudarsana Kalluru 			    enum ethtool_phys_id_state state)
8403d971cbdSSudarsana Kalluru {
8413d971cbdSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
8423d971cbdSSudarsana Kalluru 	u8 led_state = 0;
8433d971cbdSSudarsana Kalluru 
8443d971cbdSSudarsana Kalluru 	switch (state) {
8453d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ACTIVE:
8463d971cbdSSudarsana Kalluru 		return 1;	/* cycle on/off once per second */
8473d971cbdSSudarsana Kalluru 
8483d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ON:
8493d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_ON;
8503d971cbdSSudarsana Kalluru 		break;
8513d971cbdSSudarsana Kalluru 
8523d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_OFF:
8533d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_OFF;
8543d971cbdSSudarsana Kalluru 		break;
8553d971cbdSSudarsana Kalluru 
8563d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_INACTIVE:
8573d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_RESTORE;
8583d971cbdSSudarsana Kalluru 		break;
8593d971cbdSSudarsana Kalluru 	}
8603d971cbdSSudarsana Kalluru 
8613d971cbdSSudarsana Kalluru 	edev->ops->common->set_led(edev->cdev, led_state);
8623d971cbdSSudarsana Kalluru 
8633d971cbdSSudarsana Kalluru 	return 0;
8643d971cbdSSudarsana Kalluru }
8653d971cbdSSudarsana Kalluru 
866961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
867961acdeaSSudarsana Reddy Kalluru {
868961acdeaSSudarsana Reddy Kalluru 	info->data = RXH_IP_SRC | RXH_IP_DST;
869961acdeaSSudarsana Reddy Kalluru 
870961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
871961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
872961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
873961acdeaSSudarsana Reddy Kalluru 		info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
874961acdeaSSudarsana Reddy Kalluru 		break;
875961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
876961acdeaSSudarsana Reddy Kalluru 		if (edev->rss_params.rss_caps & QED_RSS_IPV4_UDP)
877961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
878961acdeaSSudarsana Reddy Kalluru 		break;
879961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
880961acdeaSSudarsana Reddy Kalluru 		if (edev->rss_params.rss_caps & QED_RSS_IPV6_UDP)
881961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
882961acdeaSSudarsana Reddy Kalluru 		break;
883961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
884961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
885961acdeaSSudarsana Reddy Kalluru 		break;
886961acdeaSSudarsana Reddy Kalluru 	default:
887961acdeaSSudarsana Reddy Kalluru 		info->data = 0;
888961acdeaSSudarsana Reddy Kalluru 		break;
889961acdeaSSudarsana Reddy Kalluru 	}
890961acdeaSSudarsana Reddy Kalluru 
891961acdeaSSudarsana Reddy Kalluru 	return 0;
892961acdeaSSudarsana Reddy Kalluru }
893961acdeaSSudarsana Reddy Kalluru 
894961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
895961acdeaSSudarsana Reddy Kalluru 			  u32 *rules __always_unused)
896961acdeaSSudarsana Reddy Kalluru {
897961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
898961acdeaSSudarsana Reddy Kalluru 
899961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
900961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXRINGS:
9019a4d7e86SSudarsana Reddy Kalluru 		info->data = QEDE_RSS_COUNT(edev);
902961acdeaSSudarsana Reddy Kalluru 		return 0;
903961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXFH:
904961acdeaSSudarsana Reddy Kalluru 		return qede_get_rss_flags(edev, info);
905961acdeaSSudarsana Reddy Kalluru 	default:
906961acdeaSSudarsana Reddy Kalluru 		DP_ERR(edev, "Command parameters not supported\n");
907961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
908961acdeaSSudarsana Reddy Kalluru 	}
909961acdeaSSudarsana Reddy Kalluru }
910961acdeaSSudarsana Reddy Kalluru 
911961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
912961acdeaSSudarsana Reddy Kalluru {
913961acdeaSSudarsana Reddy Kalluru 	struct qed_update_vport_params vport_update_params;
914961acdeaSSudarsana Reddy Kalluru 	u8 set_caps = 0, clr_caps = 0;
915961acdeaSSudarsana Reddy Kalluru 
916961acdeaSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
917961acdeaSSudarsana Reddy Kalluru 		   "Set rss flags command parameters: flow type = %d, data = %llu\n",
918961acdeaSSudarsana Reddy Kalluru 		   info->flow_type, info->data);
919961acdeaSSudarsana Reddy Kalluru 
920961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
921961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
922961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
923961acdeaSSudarsana Reddy Kalluru 		/* For TCP only 4-tuple hash is supported */
924961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST |
925961acdeaSSudarsana Reddy Kalluru 				  RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
926961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
927961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
928961acdeaSSudarsana Reddy Kalluru 		}
929961acdeaSSudarsana Reddy Kalluru 		return 0;
930961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
931961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
932961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
933961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
934961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV4_UDP;
935961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
936961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
937961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
938961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV4_UDP;
939961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
940961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
941961acdeaSSudarsana Reddy Kalluru 		} else {
942961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
943961acdeaSSudarsana Reddy Kalluru 		}
944961acdeaSSudarsana Reddy Kalluru 		break;
945961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
946961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
947961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
948961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
949961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV6_UDP;
950961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
951961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
952961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
953961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV6_UDP;
954961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
955961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
956961acdeaSSudarsana Reddy Kalluru 		} else {
957961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
958961acdeaSSudarsana Reddy Kalluru 		}
959961acdeaSSudarsana Reddy Kalluru 		break;
960961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
961961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
962961acdeaSSudarsana Reddy Kalluru 		/* For IP only 2-tuple hash is supported */
963961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) {
964961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
965961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
966961acdeaSSudarsana Reddy Kalluru 		}
967961acdeaSSudarsana Reddy Kalluru 		return 0;
968961acdeaSSudarsana Reddy Kalluru 	case SCTP_V4_FLOW:
969961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V4_FLOW:
970961acdeaSSudarsana Reddy Kalluru 	case AH_V4_FLOW:
971961acdeaSSudarsana Reddy Kalluru 	case ESP_V4_FLOW:
972961acdeaSSudarsana Reddy Kalluru 	case SCTP_V6_FLOW:
973961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V6_FLOW:
974961acdeaSSudarsana Reddy Kalluru 	case AH_V6_FLOW:
975961acdeaSSudarsana Reddy Kalluru 	case ESP_V6_FLOW:
976961acdeaSSudarsana Reddy Kalluru 	case IP_USER_FLOW:
977961acdeaSSudarsana Reddy Kalluru 	case ETHER_FLOW:
978961acdeaSSudarsana Reddy Kalluru 		/* RSS is not supported for these protocols */
979961acdeaSSudarsana Reddy Kalluru 		if (info->data) {
980961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
981961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
982961acdeaSSudarsana Reddy Kalluru 		}
983961acdeaSSudarsana Reddy Kalluru 		return 0;
984961acdeaSSudarsana Reddy Kalluru 	default:
985961acdeaSSudarsana Reddy Kalluru 		return -EINVAL;
986961acdeaSSudarsana Reddy Kalluru 	}
987961acdeaSSudarsana Reddy Kalluru 
988961acdeaSSudarsana Reddy Kalluru 	/* No action is needed if there is no change in the rss capability */
989961acdeaSSudarsana Reddy Kalluru 	if (edev->rss_params.rss_caps == ((edev->rss_params.rss_caps &
990961acdeaSSudarsana Reddy Kalluru 					   ~clr_caps) | set_caps))
991961acdeaSSudarsana Reddy Kalluru 		return 0;
992961acdeaSSudarsana Reddy Kalluru 
993961acdeaSSudarsana Reddy Kalluru 	/* Update internal configuration */
994961acdeaSSudarsana Reddy Kalluru 	edev->rss_params.rss_caps = (edev->rss_params.rss_caps & ~clr_caps) |
995961acdeaSSudarsana Reddy Kalluru 				    set_caps;
996961acdeaSSudarsana Reddy Kalluru 	edev->rss_params_inited |= QEDE_RSS_CAPS_INITED;
997961acdeaSSudarsana Reddy Kalluru 
998961acdeaSSudarsana Reddy Kalluru 	/* Re-configure if possible */
999961acdeaSSudarsana Reddy Kalluru 	if (netif_running(edev->ndev)) {
1000961acdeaSSudarsana Reddy Kalluru 		memset(&vport_update_params, 0, sizeof(vport_update_params));
1001961acdeaSSudarsana Reddy Kalluru 		vport_update_params.update_rss_flg = 1;
1002961acdeaSSudarsana Reddy Kalluru 		vport_update_params.vport_id = 0;
1003961acdeaSSudarsana Reddy Kalluru 		memcpy(&vport_update_params.rss_params, &edev->rss_params,
1004961acdeaSSudarsana Reddy Kalluru 		       sizeof(vport_update_params.rss_params));
1005961acdeaSSudarsana Reddy Kalluru 		return edev->ops->vport_update(edev->cdev,
1006961acdeaSSudarsana Reddy Kalluru 					       &vport_update_params);
1007961acdeaSSudarsana Reddy Kalluru 	}
1008961acdeaSSudarsana Reddy Kalluru 
1009961acdeaSSudarsana Reddy Kalluru 	return 0;
1010961acdeaSSudarsana Reddy Kalluru }
1011961acdeaSSudarsana Reddy Kalluru 
1012961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
1013961acdeaSSudarsana Reddy Kalluru {
1014961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1015961acdeaSSudarsana Reddy Kalluru 
1016961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
1017961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_SRXFH:
1018961acdeaSSudarsana Reddy Kalluru 		return qede_set_rss_flags(edev, info);
1019961acdeaSSudarsana Reddy Kalluru 	default:
1020961acdeaSSudarsana Reddy Kalluru 		DP_INFO(edev, "Command parameters not supported\n");
1021961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1022961acdeaSSudarsana Reddy Kalluru 	}
1023961acdeaSSudarsana Reddy Kalluru }
1024961acdeaSSudarsana Reddy Kalluru 
1025961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev)
1026961acdeaSSudarsana Reddy Kalluru {
1027961acdeaSSudarsana Reddy Kalluru 	return QED_RSS_IND_TABLE_SIZE;
1028961acdeaSSudarsana Reddy Kalluru }
1029961acdeaSSudarsana Reddy Kalluru 
1030961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev)
1031961acdeaSSudarsana Reddy Kalluru {
1032961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1033961acdeaSSudarsana Reddy Kalluru 
1034961acdeaSSudarsana Reddy Kalluru 	return sizeof(edev->rss_params.rss_key);
1035961acdeaSSudarsana Reddy Kalluru }
1036961acdeaSSudarsana Reddy Kalluru 
1037961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc)
1038961acdeaSSudarsana Reddy Kalluru {
1039961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1040961acdeaSSudarsana Reddy Kalluru 	int i;
1041961acdeaSSudarsana Reddy Kalluru 
1042961acdeaSSudarsana Reddy Kalluru 	if (hfunc)
1043961acdeaSSudarsana Reddy Kalluru 		*hfunc = ETH_RSS_HASH_TOP;
1044961acdeaSSudarsana Reddy Kalluru 
1045961acdeaSSudarsana Reddy Kalluru 	if (!indir)
1046961acdeaSSudarsana Reddy Kalluru 		return 0;
1047961acdeaSSudarsana Reddy Kalluru 
1048961acdeaSSudarsana Reddy Kalluru 	for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1049961acdeaSSudarsana Reddy Kalluru 		indir[i] = edev->rss_params.rss_ind_table[i];
1050961acdeaSSudarsana Reddy Kalluru 
1051961acdeaSSudarsana Reddy Kalluru 	if (key)
1052961acdeaSSudarsana Reddy Kalluru 		memcpy(key, edev->rss_params.rss_key,
1053961acdeaSSudarsana Reddy Kalluru 		       qede_get_rxfh_key_size(dev));
1054961acdeaSSudarsana Reddy Kalluru 
1055961acdeaSSudarsana Reddy Kalluru 	return 0;
1056961acdeaSSudarsana Reddy Kalluru }
1057961acdeaSSudarsana Reddy Kalluru 
1058961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir,
1059961acdeaSSudarsana Reddy Kalluru 			 const u8 *key, const u8 hfunc)
1060961acdeaSSudarsana Reddy Kalluru {
1061961acdeaSSudarsana Reddy Kalluru 	struct qed_update_vport_params vport_update_params;
1062961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1063961acdeaSSudarsana Reddy Kalluru 	int i;
1064961acdeaSSudarsana Reddy Kalluru 
1065ba300ce3SSudarsana Reddy Kalluru 	if (edev->dev_info.common.num_hwfns > 1) {
1066ba300ce3SSudarsana Reddy Kalluru 		DP_INFO(edev,
1067ba300ce3SSudarsana Reddy Kalluru 			"RSS configuration is not supported for 100G devices\n");
1068ba300ce3SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1069ba300ce3SSudarsana Reddy Kalluru 	}
1070ba300ce3SSudarsana Reddy Kalluru 
1071961acdeaSSudarsana Reddy Kalluru 	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
1072961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1073961acdeaSSudarsana Reddy Kalluru 
1074961acdeaSSudarsana Reddy Kalluru 	if (!indir && !key)
1075961acdeaSSudarsana Reddy Kalluru 		return 0;
1076961acdeaSSudarsana Reddy Kalluru 
1077961acdeaSSudarsana Reddy Kalluru 	if (indir) {
1078961acdeaSSudarsana Reddy Kalluru 		for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1079961acdeaSSudarsana Reddy Kalluru 			edev->rss_params.rss_ind_table[i] = indir[i];
1080961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_INDIR_INITED;
1081961acdeaSSudarsana Reddy Kalluru 	}
1082961acdeaSSudarsana Reddy Kalluru 
1083961acdeaSSudarsana Reddy Kalluru 	if (key) {
1084961acdeaSSudarsana Reddy Kalluru 		memcpy(&edev->rss_params.rss_key, key,
1085961acdeaSSudarsana Reddy Kalluru 		       qede_get_rxfh_key_size(dev));
1086961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_KEY_INITED;
1087961acdeaSSudarsana Reddy Kalluru 	}
1088961acdeaSSudarsana Reddy Kalluru 
1089961acdeaSSudarsana Reddy Kalluru 	if (netif_running(edev->ndev)) {
1090961acdeaSSudarsana Reddy Kalluru 		memset(&vport_update_params, 0, sizeof(vport_update_params));
1091961acdeaSSudarsana Reddy Kalluru 		vport_update_params.update_rss_flg = 1;
1092961acdeaSSudarsana Reddy Kalluru 		vport_update_params.vport_id = 0;
1093961acdeaSSudarsana Reddy Kalluru 		memcpy(&vport_update_params.rss_params, &edev->rss_params,
1094961acdeaSSudarsana Reddy Kalluru 		       sizeof(vport_update_params.rss_params));
1095961acdeaSSudarsana Reddy Kalluru 		return edev->ops->vport_update(edev->cdev,
1096961acdeaSSudarsana Reddy Kalluru 					       &vport_update_params);
1097961acdeaSSudarsana Reddy Kalluru 	}
1098961acdeaSSudarsana Reddy Kalluru 
1099961acdeaSSudarsana Reddy Kalluru 	return 0;
1100961acdeaSSudarsana Reddy Kalluru }
1101961acdeaSSudarsana Reddy Kalluru 
110216f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */
110316f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev)
110416f46bf0SSudarsana Reddy Kalluru {
110516f46bf0SSudarsana Reddy Kalluru 	int i;
110616f46bf0SSudarsana Reddy Kalluru 
110716f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev))
110816f46bf0SSudarsana Reddy Kalluru 		return;
110916f46bf0SSudarsana Reddy Kalluru 
11109a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
111116f46bf0SSudarsana Reddy Kalluru 		/* Update and reenable interrupts */
111216f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1);
111316f46bf0SSudarsana Reddy Kalluru 		napi_enable(&edev->fp_array[i].napi);
111416f46bf0SSudarsana Reddy Kalluru 	}
111516f46bf0SSudarsana Reddy Kalluru }
111616f46bf0SSudarsana Reddy Kalluru 
111716f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */
111816f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev)
111916f46bf0SSudarsana Reddy Kalluru {
112016f46bf0SSudarsana Reddy Kalluru 	int i;
112116f46bf0SSudarsana Reddy Kalluru 
11229a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
112316f46bf0SSudarsana Reddy Kalluru 		napi_disable(&edev->fp_array[i].napi);
112416f46bf0SSudarsana Reddy Kalluru 		/* Disable interrupts */
112516f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0);
112616f46bf0SSudarsana Reddy Kalluru 	}
112716f46bf0SSudarsana Reddy Kalluru }
112816f46bf0SSudarsana Reddy Kalluru 
112916f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev,
113016f46bf0SSudarsana Reddy Kalluru 					  struct sk_buff *skb)
113116f46bf0SSudarsana Reddy Kalluru {
11329a4d7e86SSudarsana Reddy Kalluru 	struct qede_tx_queue *txq = NULL;
113316f46bf0SSudarsana Reddy Kalluru 	struct eth_tx_1st_bd *first_bd;
113416f46bf0SSudarsana Reddy Kalluru 	dma_addr_t mapping;
113516f46bf0SSudarsana Reddy Kalluru 	int i, idx, val;
113616f46bf0SSudarsana Reddy Kalluru 
11379a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
11389a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
11399a4d7e86SSudarsana Reddy Kalluru 			txq = edev->fp_array[i].txqs;
11409a4d7e86SSudarsana Reddy Kalluru 			break;
11419a4d7e86SSudarsana Reddy Kalluru 		}
11429a4d7e86SSudarsana Reddy Kalluru 	}
11439a4d7e86SSudarsana Reddy Kalluru 
11449a4d7e86SSudarsana Reddy Kalluru 	if (!txq) {
11459a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx path is not available\n");
11469a4d7e86SSudarsana Reddy Kalluru 		return -1;
11479a4d7e86SSudarsana Reddy Kalluru 	}
11489a4d7e86SSudarsana Reddy Kalluru 
114916f46bf0SSudarsana Reddy Kalluru 	/* Fill the entry in the SW ring and the BDs in the FW ring */
115016f46bf0SSudarsana Reddy Kalluru 	idx = txq->sw_tx_prod & NUM_TX_BDS_MAX;
115116f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_ring[idx].skb = skb;
115216f46bf0SSudarsana Reddy Kalluru 	first_bd = qed_chain_produce(&txq->tx_pbl);
115316f46bf0SSudarsana Reddy Kalluru 	memset(first_bd, 0, sizeof(*first_bd));
115416f46bf0SSudarsana Reddy Kalluru 	val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
115516f46bf0SSudarsana Reddy Kalluru 	first_bd->data.bd_flags.bitfields = val;
1156351a4dedSYuval Mintz 	val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK;
1157351a4dedSYuval Mintz 	first_bd->data.bitfields |= (val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT);
115816f46bf0SSudarsana Reddy Kalluru 
115916f46bf0SSudarsana Reddy Kalluru 	/* Map skb linear data for DMA and set in the first BD */
116016f46bf0SSudarsana Reddy Kalluru 	mapping = dma_map_single(&edev->pdev->dev, skb->data,
116116f46bf0SSudarsana Reddy Kalluru 				 skb_headlen(skb), DMA_TO_DEVICE);
116216f46bf0SSudarsana Reddy Kalluru 	if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
116316f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "SKB mapping failed\n");
116416f46bf0SSudarsana Reddy Kalluru 		return -ENOMEM;
116516f46bf0SSudarsana Reddy Kalluru 	}
116616f46bf0SSudarsana Reddy Kalluru 	BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb));
116716f46bf0SSudarsana Reddy Kalluru 
116816f46bf0SSudarsana Reddy Kalluru 	/* update the first BD with the actual num BDs */
116916f46bf0SSudarsana Reddy Kalluru 	first_bd->data.nbds = 1;
117016f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_prod++;
117116f46bf0SSudarsana Reddy Kalluru 	/* 'next page' entries are counted in the producer value */
117216f46bf0SSudarsana Reddy Kalluru 	val = cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl));
117316f46bf0SSudarsana Reddy Kalluru 	txq->tx_db.data.bd_prod = val;
117416f46bf0SSudarsana Reddy Kalluru 
117516f46bf0SSudarsana Reddy Kalluru 	/* wmb makes sure that the BDs data is updated before updating the
117616f46bf0SSudarsana Reddy Kalluru 	 * producer, otherwise FW may read old data from the BDs.
117716f46bf0SSudarsana Reddy Kalluru 	 */
117816f46bf0SSudarsana Reddy Kalluru 	wmb();
117916f46bf0SSudarsana Reddy Kalluru 	barrier();
118016f46bf0SSudarsana Reddy Kalluru 	writel(txq->tx_db.raw, txq->doorbell_addr);
118116f46bf0SSudarsana Reddy Kalluru 
118216f46bf0SSudarsana Reddy Kalluru 	/* mmiowb is needed to synchronize doorbell writes from more than one
118316f46bf0SSudarsana Reddy Kalluru 	 * processor. It guarantees that the write arrives to the device before
118416f46bf0SSudarsana Reddy Kalluru 	 * the queue lock is released and another start_xmit is called (possibly
118516f46bf0SSudarsana Reddy Kalluru 	 * on another CPU). Without this barrier, the next doorbell can bypass
118616f46bf0SSudarsana Reddy Kalluru 	 * this doorbell. This is applicable to IA64/Altix systems.
118716f46bf0SSudarsana Reddy Kalluru 	 */
118816f46bf0SSudarsana Reddy Kalluru 	mmiowb();
118916f46bf0SSudarsana Reddy Kalluru 
119016f46bf0SSudarsana Reddy Kalluru 	for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
119116f46bf0SSudarsana Reddy Kalluru 		if (qede_txq_has_work(txq))
119216f46bf0SSudarsana Reddy Kalluru 			break;
119316f46bf0SSudarsana Reddy Kalluru 		usleep_range(100, 200);
119416f46bf0SSudarsana Reddy Kalluru 	}
119516f46bf0SSudarsana Reddy Kalluru 
119616f46bf0SSudarsana Reddy Kalluru 	if (!qede_txq_has_work(txq)) {
119716f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx completion didn't happen\n");
119816f46bf0SSudarsana Reddy Kalluru 		return -1;
119916f46bf0SSudarsana Reddy Kalluru 	}
120016f46bf0SSudarsana Reddy Kalluru 
120116f46bf0SSudarsana Reddy Kalluru 	first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
1202fabd545cSManish Chopra 	dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
120316f46bf0SSudarsana Reddy Kalluru 			 BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
120416f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_cons++;
120516f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_ring[idx].skb = NULL;
120616f46bf0SSudarsana Reddy Kalluru 
120716f46bf0SSudarsana Reddy Kalluru 	return 0;
120816f46bf0SSudarsana Reddy Kalluru }
120916f46bf0SSudarsana Reddy Kalluru 
121016f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev)
121116f46bf0SSudarsana Reddy Kalluru {
121216f46bf0SSudarsana Reddy Kalluru 	u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len;
121316f46bf0SSudarsana Reddy Kalluru 	struct eth_fast_path_rx_reg_cqe *fp_cqe;
12149a4d7e86SSudarsana Reddy Kalluru 	struct qede_rx_queue *rxq = NULL;
121516f46bf0SSudarsana Reddy Kalluru 	struct sw_rx_data *sw_rx_data;
121616f46bf0SSudarsana Reddy Kalluru 	union eth_rx_cqe *cqe;
1217837d4eb6SSudarsana Reddy Kalluru 	int i, rc = 0;
121816f46bf0SSudarsana Reddy Kalluru 	u8 *data_ptr;
121916f46bf0SSudarsana Reddy Kalluru 
12209a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
12219a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
12229a4d7e86SSudarsana Reddy Kalluru 			rxq = edev->fp_array[i].rxq;
12239a4d7e86SSudarsana Reddy Kalluru 			break;
12249a4d7e86SSudarsana Reddy Kalluru 		}
12259a4d7e86SSudarsana Reddy Kalluru 	}
12269a4d7e86SSudarsana Reddy Kalluru 
12279a4d7e86SSudarsana Reddy Kalluru 	if (!rxq) {
12289a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Rx path is not available\n");
12299a4d7e86SSudarsana Reddy Kalluru 		return -1;
12309a4d7e86SSudarsana Reddy Kalluru 	}
12319a4d7e86SSudarsana Reddy Kalluru 
123216f46bf0SSudarsana Reddy Kalluru 	/* The packet is expected to receive on rx-queue 0 even though RSS is
123316f46bf0SSudarsana Reddy Kalluru 	 * enabled. This is because the queue 0 is configured as the default
123416f46bf0SSudarsana Reddy Kalluru 	 * queue and that the loopback traffic is not IP.
123516f46bf0SSudarsana Reddy Kalluru 	 */
123616f46bf0SSudarsana Reddy Kalluru 	for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
123716f46bf0SSudarsana Reddy Kalluru 		if (!qede_has_rx_work(rxq)) {
1238837d4eb6SSudarsana Reddy Kalluru 			usleep_range(100, 200);
1239837d4eb6SSudarsana Reddy Kalluru 			continue;
124016f46bf0SSudarsana Reddy Kalluru 		}
124116f46bf0SSudarsana Reddy Kalluru 
124216f46bf0SSudarsana Reddy Kalluru 		hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
124316f46bf0SSudarsana Reddy Kalluru 		sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
124416f46bf0SSudarsana Reddy Kalluru 
1245837d4eb6SSudarsana Reddy Kalluru 		/* Memory barrier to prevent the CPU from doing speculative
1246837d4eb6SSudarsana Reddy Kalluru 		 * reads of CQE/BD before reading hw_comp_cons. If the CQE is
1247837d4eb6SSudarsana Reddy Kalluru 		 * read before it is written by FW, then FW writes CQE and SB,
1248837d4eb6SSudarsana Reddy Kalluru 		 * and then the CPU reads the hw_comp_cons, it will use an old
1249837d4eb6SSudarsana Reddy Kalluru 		 * CQE.
125016f46bf0SSudarsana Reddy Kalluru 		 */
125116f46bf0SSudarsana Reddy Kalluru 		rmb();
125216f46bf0SSudarsana Reddy Kalluru 
125316f46bf0SSudarsana Reddy Kalluru 		/* Get the CQE from the completion ring */
125416f46bf0SSudarsana Reddy Kalluru 		cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring);
125516f46bf0SSudarsana Reddy Kalluru 
125616f46bf0SSudarsana Reddy Kalluru 		/* Get the data from the SW ring */
125716f46bf0SSudarsana Reddy Kalluru 		sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
125816f46bf0SSudarsana Reddy Kalluru 		sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
125916f46bf0SSudarsana Reddy Kalluru 		fp_cqe = &cqe->fast_path_regular;
126016f46bf0SSudarsana Reddy Kalluru 		len =  le16_to_cpu(fp_cqe->len_on_first_bd);
126116f46bf0SSudarsana Reddy Kalluru 		data_ptr = (u8 *)(page_address(sw_rx_data->data) +
1262837d4eb6SSudarsana Reddy Kalluru 				  fp_cqe->placement_offset +
1263837d4eb6SSudarsana Reddy Kalluru 				  sw_rx_data->page_offset);
1264837d4eb6SSudarsana Reddy Kalluru 		if (ether_addr_equal(data_ptr,  edev->ndev->dev_addr) &&
1265837d4eb6SSudarsana Reddy Kalluru 		    ether_addr_equal(data_ptr + ETH_ALEN,
1266837d4eb6SSudarsana Reddy Kalluru 				     edev->ndev->dev_addr)) {
126716f46bf0SSudarsana Reddy Kalluru 			for (i = ETH_HLEN; i < len; i++)
126816f46bf0SSudarsana Reddy Kalluru 				if (data_ptr[i] != (unsigned char)(i & 0xff)) {
1269837d4eb6SSudarsana Reddy Kalluru 					rc = -1;
1270837d4eb6SSudarsana Reddy Kalluru 					break;
127116f46bf0SSudarsana Reddy Kalluru 				}
127216f46bf0SSudarsana Reddy Kalluru 
127316f46bf0SSudarsana Reddy Kalluru 			qede_recycle_rx_bd_ring(rxq, edev, 1);
1274837d4eb6SSudarsana Reddy Kalluru 			qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1275837d4eb6SSudarsana Reddy Kalluru 			break;
1276837d4eb6SSudarsana Reddy Kalluru 		}
127716f46bf0SSudarsana Reddy Kalluru 
1278837d4eb6SSudarsana Reddy Kalluru 		DP_INFO(edev, "Not the transmitted packet\n");
1279837d4eb6SSudarsana Reddy Kalluru 		qede_recycle_rx_bd_ring(rxq, edev, 1);
1280837d4eb6SSudarsana Reddy Kalluru 		qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1281837d4eb6SSudarsana Reddy Kalluru 	}
1282837d4eb6SSudarsana Reddy Kalluru 
1283837d4eb6SSudarsana Reddy Kalluru 	if (i == QEDE_SELFTEST_POLL_COUNT) {
1284837d4eb6SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Failed to receive the traffic\n");
1285837d4eb6SSudarsana Reddy Kalluru 		return -1;
1286837d4eb6SSudarsana Reddy Kalluru 	}
1287837d4eb6SSudarsana Reddy Kalluru 
1288837d4eb6SSudarsana Reddy Kalluru 	qede_update_rx_prod(edev, rxq);
1289837d4eb6SSudarsana Reddy Kalluru 
1290837d4eb6SSudarsana Reddy Kalluru 	return rc;
129116f46bf0SSudarsana Reddy Kalluru }
129216f46bf0SSudarsana Reddy Kalluru 
129316f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode)
129416f46bf0SSudarsana Reddy Kalluru {
129516f46bf0SSudarsana Reddy Kalluru 	struct qed_link_params link_params;
129616f46bf0SSudarsana Reddy Kalluru 	struct sk_buff *skb = NULL;
129716f46bf0SSudarsana Reddy Kalluru 	int rc = 0, i;
129816f46bf0SSudarsana Reddy Kalluru 	u32 pkt_size;
129916f46bf0SSudarsana Reddy Kalluru 	u8 *packet;
130016f46bf0SSudarsana Reddy Kalluru 
130116f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev)) {
130216f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Interface is down\n");
130316f46bf0SSudarsana Reddy Kalluru 		return -EINVAL;
130416f46bf0SSudarsana Reddy Kalluru 	}
130516f46bf0SSudarsana Reddy Kalluru 
130616f46bf0SSudarsana Reddy Kalluru 	qede_netif_stop(edev);
130716f46bf0SSudarsana Reddy Kalluru 
130816f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Loopback mode */
130916f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
131016f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
131116f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
131216f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = loopback_mode;
131316f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
131416f46bf0SSudarsana Reddy Kalluru 
131516f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
131616f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
131716f46bf0SSudarsana Reddy Kalluru 
131816f46bf0SSudarsana Reddy Kalluru 	/* prepare the loopback packet */
131916f46bf0SSudarsana Reddy Kalluru 	pkt_size = edev->ndev->mtu + ETH_HLEN;
132016f46bf0SSudarsana Reddy Kalluru 
132116f46bf0SSudarsana Reddy Kalluru 	skb = netdev_alloc_skb(edev->ndev, pkt_size);
132216f46bf0SSudarsana Reddy Kalluru 	if (!skb) {
132316f46bf0SSudarsana Reddy Kalluru 		DP_INFO(edev, "Can't allocate skb\n");
132416f46bf0SSudarsana Reddy Kalluru 		rc = -ENOMEM;
132516f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
132616f46bf0SSudarsana Reddy Kalluru 	}
132716f46bf0SSudarsana Reddy Kalluru 	packet = skb_put(skb, pkt_size);
132816f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet, edev->ndev->dev_addr);
132916f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr);
133016f46bf0SSudarsana Reddy Kalluru 	memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN)));
133116f46bf0SSudarsana Reddy Kalluru 	for (i = ETH_HLEN; i < pkt_size; i++)
133216f46bf0SSudarsana Reddy Kalluru 		packet[i] = (unsigned char)(i & 0xff);
133316f46bf0SSudarsana Reddy Kalluru 
133416f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_transmit_traffic(edev, skb);
133516f46bf0SSudarsana Reddy Kalluru 	if (rc)
133616f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
133716f46bf0SSudarsana Reddy Kalluru 
133816f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_receive_traffic(edev);
133916f46bf0SSudarsana Reddy Kalluru 	if (rc)
134016f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
134116f46bf0SSudarsana Reddy Kalluru 
134216f46bf0SSudarsana Reddy Kalluru 	DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n");
134316f46bf0SSudarsana Reddy Kalluru 
134416f46bf0SSudarsana Reddy Kalluru test_loopback_exit:
134516f46bf0SSudarsana Reddy Kalluru 	dev_kfree_skb(skb);
134616f46bf0SSudarsana Reddy Kalluru 
134716f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Normal mode */
134816f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
134916f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
135016f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
135116f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = QED_LINK_LOOPBACK_NONE;
135216f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
135316f46bf0SSudarsana Reddy Kalluru 
135416f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
135516f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
135616f46bf0SSudarsana Reddy Kalluru 
135716f46bf0SSudarsana Reddy Kalluru 	qede_netif_start(edev);
135816f46bf0SSudarsana Reddy Kalluru 
135916f46bf0SSudarsana Reddy Kalluru 	return rc;
136016f46bf0SSudarsana Reddy Kalluru }
136116f46bf0SSudarsana Reddy Kalluru 
13623044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev,
13633044a02eSSudarsana Reddy Kalluru 			   struct ethtool_test *etest, u64 *buf)
13643044a02eSSudarsana Reddy Kalluru {
13653044a02eSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
13663044a02eSSudarsana Reddy Kalluru 
13673044a02eSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
13683044a02eSSudarsana Reddy Kalluru 		   "Self-test command parameters: offline = %d, external_lb = %d\n",
13693044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_OFFLINE),
13703044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2);
13713044a02eSSudarsana Reddy Kalluru 
13723044a02eSSudarsana Reddy Kalluru 	memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX);
13733044a02eSSudarsana Reddy Kalluru 
137416f46bf0SSudarsana Reddy Kalluru 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
137516f46bf0SSudarsana Reddy Kalluru 		if (qede_selftest_run_loopback(edev,
137616f46bf0SSudarsana Reddy Kalluru 					       QED_LINK_LOOPBACK_INT_PHY)) {
137716f46bf0SSudarsana Reddy Kalluru 			buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1;
137816f46bf0SSudarsana Reddy Kalluru 			etest->flags |= ETH_TEST_FL_FAILED;
137916f46bf0SSudarsana Reddy Kalluru 		}
138016f46bf0SSudarsana Reddy Kalluru 	}
138116f46bf0SSudarsana Reddy Kalluru 
13823044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) {
13833044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1;
13843044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
13853044a02eSSudarsana Reddy Kalluru 	}
13863044a02eSSudarsana Reddy Kalluru 
13873044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_memory(edev->cdev)) {
13883044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_MEMORY_TEST] = 1;
13893044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
13903044a02eSSudarsana Reddy Kalluru 	}
13913044a02eSSudarsana Reddy Kalluru 
13923044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_register(edev->cdev)) {
13933044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_REGISTER_TEST] = 1;
13943044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
13953044a02eSSudarsana Reddy Kalluru 	}
13963044a02eSSudarsana Reddy Kalluru 
13973044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_clock(edev->cdev)) {
13983044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_CLOCK_TEST] = 1;
13993044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
14003044a02eSSudarsana Reddy Kalluru 	}
14013044a02eSSudarsana Reddy Kalluru }
14023044a02eSSudarsana Reddy Kalluru 
14033d789994SManish Chopra static int qede_set_tunable(struct net_device *dev,
14043d789994SManish Chopra 			    const struct ethtool_tunable *tuna,
14053d789994SManish Chopra 			    const void *data)
14063d789994SManish Chopra {
14073d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
14083d789994SManish Chopra 	u32 val;
14093d789994SManish Chopra 
14103d789994SManish Chopra 	switch (tuna->id) {
14113d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
14123d789994SManish Chopra 		val = *(u32 *)data;
14133d789994SManish Chopra 		if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) {
14143d789994SManish Chopra 			DP_VERBOSE(edev, QED_MSG_DEBUG,
14153d789994SManish Chopra 				   "Invalid rx copy break value, range is [%u, %u]",
14163d789994SManish Chopra 				   QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE);
14173d789994SManish Chopra 			return -EINVAL;
14183d789994SManish Chopra 		}
14193d789994SManish Chopra 
14203d789994SManish Chopra 		edev->rx_copybreak = *(u32 *)data;
14213d789994SManish Chopra 		break;
14223d789994SManish Chopra 	default:
14233d789994SManish Chopra 		return -EOPNOTSUPP;
14243d789994SManish Chopra 	}
14253d789994SManish Chopra 
14263d789994SManish Chopra 	return 0;
14273d789994SManish Chopra }
14283d789994SManish Chopra 
14293d789994SManish Chopra static int qede_get_tunable(struct net_device *dev,
14303d789994SManish Chopra 			    const struct ethtool_tunable *tuna, void *data)
14313d789994SManish Chopra {
14323d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
14333d789994SManish Chopra 
14343d789994SManish Chopra 	switch (tuna->id) {
14353d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
14363d789994SManish Chopra 		*(u32 *)data = edev->rx_copybreak;
14373d789994SManish Chopra 		break;
14383d789994SManish Chopra 	default:
14393d789994SManish Chopra 		return -EOPNOTSUPP;
14403d789994SManish Chopra 	}
14413d789994SManish Chopra 
14423d789994SManish Chopra 	return 0;
14433d789994SManish Chopra }
14443d789994SManish Chopra 
1445133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = {
1446054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
1447054c67d1SSudarsana Reddy Kalluru 	.set_link_ksettings = qede_set_link_ksettings,
1448133fac0eSSudarsana Kalluru 	.get_drvinfo = qede_get_drvinfo,
1449e0971c83STomer Tayar 	.get_regs_len = qede_get_regs_len,
1450e0971c83STomer Tayar 	.get_regs = qede_get_regs,
1451133fac0eSSudarsana Kalluru 	.get_msglevel = qede_get_msglevel,
1452133fac0eSSudarsana Kalluru 	.set_msglevel = qede_set_msglevel,
145332a7a570SSudarsana Kalluru 	.nway_reset = qede_nway_reset,
1454133fac0eSSudarsana Kalluru 	.get_link = qede_get_link,
1455d552fa84SSudarsana Reddy Kalluru 	.get_coalesce = qede_get_coalesce,
1456d552fa84SSudarsana Reddy Kalluru 	.set_coalesce = qede_set_coalesce,
145701ef7e05SSudarsana Kalluru 	.get_ringparam = qede_get_ringparam,
145801ef7e05SSudarsana Kalluru 	.set_ringparam = qede_set_ringparam,
14590f7db144SSudarsana Kalluru 	.get_pauseparam = qede_get_pauseparam,
14600f7db144SSudarsana Kalluru 	.set_pauseparam = qede_set_pauseparam,
1461133fac0eSSudarsana Kalluru 	.get_strings = qede_get_strings,
14623d971cbdSSudarsana Kalluru 	.set_phys_id = qede_set_phys_id,
1463133fac0eSSudarsana Kalluru 	.get_ethtool_stats = qede_get_ethtool_stats,
1464f3e72109SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
1465133fac0eSSudarsana Kalluru 	.get_sset_count = qede_get_sset_count,
1466961acdeaSSudarsana Reddy Kalluru 	.get_rxnfc = qede_get_rxnfc,
1467961acdeaSSudarsana Reddy Kalluru 	.set_rxnfc = qede_set_rxnfc,
1468961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
1469961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_key_size = qede_get_rxfh_key_size,
1470961acdeaSSudarsana Reddy Kalluru 	.get_rxfh = qede_get_rxfh,
1471961acdeaSSudarsana Reddy Kalluru 	.set_rxfh = qede_set_rxfh,
14728edf049dSSudarsana Kalluru 	.get_channels = qede_get_channels,
14738edf049dSSudarsana Kalluru 	.set_channels = qede_set_channels,
14743044a02eSSudarsana Reddy Kalluru 	.self_test = qede_self_test,
14753d789994SManish Chopra 	.get_tunable = qede_get_tunable,
14763d789994SManish Chopra 	.set_tunable = qede_set_tunable,
1477133fac0eSSudarsana Kalluru };
1478133fac0eSSudarsana Kalluru 
1479fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = {
1480054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
1481fefb0202SYuval Mintz 	.get_drvinfo = qede_get_drvinfo,
1482fefb0202SYuval Mintz 	.get_msglevel = qede_get_msglevel,
1483fefb0202SYuval Mintz 	.set_msglevel = qede_set_msglevel,
1484fefb0202SYuval Mintz 	.get_link = qede_get_link,
1485fefb0202SYuval Mintz 	.get_ringparam = qede_get_ringparam,
1486fefb0202SYuval Mintz 	.set_ringparam = qede_set_ringparam,
1487fefb0202SYuval Mintz 	.get_strings = qede_get_strings,
1488fefb0202SYuval Mintz 	.get_ethtool_stats = qede_get_ethtool_stats,
1489fefb0202SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
1490fefb0202SYuval Mintz 	.get_sset_count = qede_get_sset_count,
1491fefb0202SYuval Mintz 	.get_rxnfc = qede_get_rxnfc,
1492fefb0202SYuval Mintz 	.set_rxnfc = qede_set_rxnfc,
1493fefb0202SYuval Mintz 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
1494fefb0202SYuval Mintz 	.get_rxfh_key_size = qede_get_rxfh_key_size,
1495fefb0202SYuval Mintz 	.get_rxfh = qede_get_rxfh,
1496fefb0202SYuval Mintz 	.set_rxfh = qede_set_rxfh,
1497fefb0202SYuval Mintz 	.get_channels = qede_get_channels,
1498fefb0202SYuval Mintz 	.set_channels = qede_set_channels,
14993d789994SManish Chopra 	.get_tunable = qede_get_tunable,
15003d789994SManish Chopra 	.set_tunable = qede_set_tunable,
1501fefb0202SYuval Mintz };
1502fefb0202SYuval Mintz 
1503133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev)
1504133fac0eSSudarsana Kalluru {
1505fefb0202SYuval Mintz 	struct qede_dev *edev = netdev_priv(dev);
1506fefb0202SYuval Mintz 
1507fefb0202SYuval Mintz 	if (IS_VF(edev))
1508fefb0202SYuval Mintz 		dev->ethtool_ops = &qede_vf_ethtool_ops;
1509fefb0202SYuval Mintz 	else
1510133fac0eSSudarsana Kalluru 		dev->ethtool_ops = &qede_ethtool_ops;
1511133fac0eSSudarsana Kalluru }
1512