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;
8258edf049dSSudarsana Kalluru 	if (netif_running(dev))
8268edf049dSSudarsana Kalluru 		qede_reload(edev, NULL, NULL);
8278edf049dSSudarsana Kalluru 
8288edf049dSSudarsana Kalluru 	return 0;
8298edf049dSSudarsana Kalluru }
8308edf049dSSudarsana Kalluru 
8313d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev,
8323d971cbdSSudarsana Kalluru 			    enum ethtool_phys_id_state state)
8333d971cbdSSudarsana Kalluru {
8343d971cbdSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
8353d971cbdSSudarsana Kalluru 	u8 led_state = 0;
8363d971cbdSSudarsana Kalluru 
8373d971cbdSSudarsana Kalluru 	switch (state) {
8383d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ACTIVE:
8393d971cbdSSudarsana Kalluru 		return 1;	/* cycle on/off once per second */
8403d971cbdSSudarsana Kalluru 
8413d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ON:
8423d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_ON;
8433d971cbdSSudarsana Kalluru 		break;
8443d971cbdSSudarsana Kalluru 
8453d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_OFF:
8463d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_OFF;
8473d971cbdSSudarsana Kalluru 		break;
8483d971cbdSSudarsana Kalluru 
8493d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_INACTIVE:
8503d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_RESTORE;
8513d971cbdSSudarsana Kalluru 		break;
8523d971cbdSSudarsana Kalluru 	}
8533d971cbdSSudarsana Kalluru 
8543d971cbdSSudarsana Kalluru 	edev->ops->common->set_led(edev->cdev, led_state);
8553d971cbdSSudarsana Kalluru 
8563d971cbdSSudarsana Kalluru 	return 0;
8573d971cbdSSudarsana Kalluru }
8583d971cbdSSudarsana Kalluru 
859961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
860961acdeaSSudarsana Reddy Kalluru {
861961acdeaSSudarsana Reddy Kalluru 	info->data = RXH_IP_SRC | RXH_IP_DST;
862961acdeaSSudarsana Reddy Kalluru 
863961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
864961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
865961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
866961acdeaSSudarsana Reddy Kalluru 		info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
867961acdeaSSudarsana Reddy Kalluru 		break;
868961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
869961acdeaSSudarsana Reddy Kalluru 		if (edev->rss_params.rss_caps & QED_RSS_IPV4_UDP)
870961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
871961acdeaSSudarsana Reddy Kalluru 		break;
872961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
873961acdeaSSudarsana Reddy Kalluru 		if (edev->rss_params.rss_caps & QED_RSS_IPV6_UDP)
874961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
875961acdeaSSudarsana Reddy Kalluru 		break;
876961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
877961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
878961acdeaSSudarsana Reddy Kalluru 		break;
879961acdeaSSudarsana Reddy Kalluru 	default:
880961acdeaSSudarsana Reddy Kalluru 		info->data = 0;
881961acdeaSSudarsana Reddy Kalluru 		break;
882961acdeaSSudarsana Reddy Kalluru 	}
883961acdeaSSudarsana Reddy Kalluru 
884961acdeaSSudarsana Reddy Kalluru 	return 0;
885961acdeaSSudarsana Reddy Kalluru }
886961acdeaSSudarsana Reddy Kalluru 
887961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
888961acdeaSSudarsana Reddy Kalluru 			  u32 *rules __always_unused)
889961acdeaSSudarsana Reddy Kalluru {
890961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
891961acdeaSSudarsana Reddy Kalluru 
892961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
893961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXRINGS:
8949a4d7e86SSudarsana Reddy Kalluru 		info->data = QEDE_RSS_COUNT(edev);
895961acdeaSSudarsana Reddy Kalluru 		return 0;
896961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXFH:
897961acdeaSSudarsana Reddy Kalluru 		return qede_get_rss_flags(edev, info);
898961acdeaSSudarsana Reddy Kalluru 	default:
899961acdeaSSudarsana Reddy Kalluru 		DP_ERR(edev, "Command parameters not supported\n");
900961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
901961acdeaSSudarsana Reddy Kalluru 	}
902961acdeaSSudarsana Reddy Kalluru }
903961acdeaSSudarsana Reddy Kalluru 
904961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
905961acdeaSSudarsana Reddy Kalluru {
906961acdeaSSudarsana Reddy Kalluru 	struct qed_update_vport_params vport_update_params;
907961acdeaSSudarsana Reddy Kalluru 	u8 set_caps = 0, clr_caps = 0;
908961acdeaSSudarsana Reddy Kalluru 
909961acdeaSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
910961acdeaSSudarsana Reddy Kalluru 		   "Set rss flags command parameters: flow type = %d, data = %llu\n",
911961acdeaSSudarsana Reddy Kalluru 		   info->flow_type, info->data);
912961acdeaSSudarsana Reddy Kalluru 
913961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
914961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
915961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
916961acdeaSSudarsana Reddy Kalluru 		/* For TCP only 4-tuple hash is supported */
917961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST |
918961acdeaSSudarsana Reddy Kalluru 				  RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
919961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
920961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
921961acdeaSSudarsana Reddy Kalluru 		}
922961acdeaSSudarsana Reddy Kalluru 		return 0;
923961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
924961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
925961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
926961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
927961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV4_UDP;
928961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
929961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
930961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
931961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV4_UDP;
932961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
933961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
934961acdeaSSudarsana Reddy Kalluru 		} else {
935961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
936961acdeaSSudarsana Reddy Kalluru 		}
937961acdeaSSudarsana Reddy Kalluru 		break;
938961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
939961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
940961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
941961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
942961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV6_UDP;
943961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
944961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
945961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
946961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV6_UDP;
947961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
948961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
949961acdeaSSudarsana Reddy Kalluru 		} else {
950961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
951961acdeaSSudarsana Reddy Kalluru 		}
952961acdeaSSudarsana Reddy Kalluru 		break;
953961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
954961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
955961acdeaSSudarsana Reddy Kalluru 		/* For IP only 2-tuple hash is supported */
956961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) {
957961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
958961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
959961acdeaSSudarsana Reddy Kalluru 		}
960961acdeaSSudarsana Reddy Kalluru 		return 0;
961961acdeaSSudarsana Reddy Kalluru 	case SCTP_V4_FLOW:
962961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V4_FLOW:
963961acdeaSSudarsana Reddy Kalluru 	case AH_V4_FLOW:
964961acdeaSSudarsana Reddy Kalluru 	case ESP_V4_FLOW:
965961acdeaSSudarsana Reddy Kalluru 	case SCTP_V6_FLOW:
966961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V6_FLOW:
967961acdeaSSudarsana Reddy Kalluru 	case AH_V6_FLOW:
968961acdeaSSudarsana Reddy Kalluru 	case ESP_V6_FLOW:
969961acdeaSSudarsana Reddy Kalluru 	case IP_USER_FLOW:
970961acdeaSSudarsana Reddy Kalluru 	case ETHER_FLOW:
971961acdeaSSudarsana Reddy Kalluru 		/* RSS is not supported for these protocols */
972961acdeaSSudarsana Reddy Kalluru 		if (info->data) {
973961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
974961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
975961acdeaSSudarsana Reddy Kalluru 		}
976961acdeaSSudarsana Reddy Kalluru 		return 0;
977961acdeaSSudarsana Reddy Kalluru 	default:
978961acdeaSSudarsana Reddy Kalluru 		return -EINVAL;
979961acdeaSSudarsana Reddy Kalluru 	}
980961acdeaSSudarsana Reddy Kalluru 
981961acdeaSSudarsana Reddy Kalluru 	/* No action is needed if there is no change in the rss capability */
982961acdeaSSudarsana Reddy Kalluru 	if (edev->rss_params.rss_caps == ((edev->rss_params.rss_caps &
983961acdeaSSudarsana Reddy Kalluru 					   ~clr_caps) | set_caps))
984961acdeaSSudarsana Reddy Kalluru 		return 0;
985961acdeaSSudarsana Reddy Kalluru 
986961acdeaSSudarsana Reddy Kalluru 	/* Update internal configuration */
987961acdeaSSudarsana Reddy Kalluru 	edev->rss_params.rss_caps = (edev->rss_params.rss_caps & ~clr_caps) |
988961acdeaSSudarsana Reddy Kalluru 				    set_caps;
989961acdeaSSudarsana Reddy Kalluru 	edev->rss_params_inited |= QEDE_RSS_CAPS_INITED;
990961acdeaSSudarsana Reddy Kalluru 
991961acdeaSSudarsana Reddy Kalluru 	/* Re-configure if possible */
992961acdeaSSudarsana Reddy Kalluru 	if (netif_running(edev->ndev)) {
993961acdeaSSudarsana Reddy Kalluru 		memset(&vport_update_params, 0, sizeof(vport_update_params));
994961acdeaSSudarsana Reddy Kalluru 		vport_update_params.update_rss_flg = 1;
995961acdeaSSudarsana Reddy Kalluru 		vport_update_params.vport_id = 0;
996961acdeaSSudarsana Reddy Kalluru 		memcpy(&vport_update_params.rss_params, &edev->rss_params,
997961acdeaSSudarsana Reddy Kalluru 		       sizeof(vport_update_params.rss_params));
998961acdeaSSudarsana Reddy Kalluru 		return edev->ops->vport_update(edev->cdev,
999961acdeaSSudarsana Reddy Kalluru 					       &vport_update_params);
1000961acdeaSSudarsana Reddy Kalluru 	}
1001961acdeaSSudarsana Reddy Kalluru 
1002961acdeaSSudarsana Reddy Kalluru 	return 0;
1003961acdeaSSudarsana Reddy Kalluru }
1004961acdeaSSudarsana Reddy Kalluru 
1005961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
1006961acdeaSSudarsana Reddy Kalluru {
1007961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1008961acdeaSSudarsana Reddy Kalluru 
1009961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
1010961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_SRXFH:
1011961acdeaSSudarsana Reddy Kalluru 		return qede_set_rss_flags(edev, info);
1012961acdeaSSudarsana Reddy Kalluru 	default:
1013961acdeaSSudarsana Reddy Kalluru 		DP_INFO(edev, "Command parameters not supported\n");
1014961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1015961acdeaSSudarsana Reddy Kalluru 	}
1016961acdeaSSudarsana Reddy Kalluru }
1017961acdeaSSudarsana Reddy Kalluru 
1018961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev)
1019961acdeaSSudarsana Reddy Kalluru {
1020961acdeaSSudarsana Reddy Kalluru 	return QED_RSS_IND_TABLE_SIZE;
1021961acdeaSSudarsana Reddy Kalluru }
1022961acdeaSSudarsana Reddy Kalluru 
1023961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev)
1024961acdeaSSudarsana Reddy Kalluru {
1025961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1026961acdeaSSudarsana Reddy Kalluru 
1027961acdeaSSudarsana Reddy Kalluru 	return sizeof(edev->rss_params.rss_key);
1028961acdeaSSudarsana Reddy Kalluru }
1029961acdeaSSudarsana Reddy Kalluru 
1030961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc)
1031961acdeaSSudarsana Reddy Kalluru {
1032961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1033961acdeaSSudarsana Reddy Kalluru 	int i;
1034961acdeaSSudarsana Reddy Kalluru 
1035961acdeaSSudarsana Reddy Kalluru 	if (hfunc)
1036961acdeaSSudarsana Reddy Kalluru 		*hfunc = ETH_RSS_HASH_TOP;
1037961acdeaSSudarsana Reddy Kalluru 
1038961acdeaSSudarsana Reddy Kalluru 	if (!indir)
1039961acdeaSSudarsana Reddy Kalluru 		return 0;
1040961acdeaSSudarsana Reddy Kalluru 
1041961acdeaSSudarsana Reddy Kalluru 	for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1042961acdeaSSudarsana Reddy Kalluru 		indir[i] = edev->rss_params.rss_ind_table[i];
1043961acdeaSSudarsana Reddy Kalluru 
1044961acdeaSSudarsana Reddy Kalluru 	if (key)
1045961acdeaSSudarsana Reddy Kalluru 		memcpy(key, edev->rss_params.rss_key,
1046961acdeaSSudarsana Reddy Kalluru 		       qede_get_rxfh_key_size(dev));
1047961acdeaSSudarsana Reddy Kalluru 
1048961acdeaSSudarsana Reddy Kalluru 	return 0;
1049961acdeaSSudarsana Reddy Kalluru }
1050961acdeaSSudarsana Reddy Kalluru 
1051961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir,
1052961acdeaSSudarsana Reddy Kalluru 			 const u8 *key, const u8 hfunc)
1053961acdeaSSudarsana Reddy Kalluru {
1054961acdeaSSudarsana Reddy Kalluru 	struct qed_update_vport_params vport_update_params;
1055961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1056961acdeaSSudarsana Reddy Kalluru 	int i;
1057961acdeaSSudarsana Reddy Kalluru 
1058ba300ce3SSudarsana Reddy Kalluru 	if (edev->dev_info.common.num_hwfns > 1) {
1059ba300ce3SSudarsana Reddy Kalluru 		DP_INFO(edev,
1060ba300ce3SSudarsana Reddy Kalluru 			"RSS configuration is not supported for 100G devices\n");
1061ba300ce3SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1062ba300ce3SSudarsana Reddy Kalluru 	}
1063ba300ce3SSudarsana Reddy Kalluru 
1064961acdeaSSudarsana Reddy Kalluru 	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
1065961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1066961acdeaSSudarsana Reddy Kalluru 
1067961acdeaSSudarsana Reddy Kalluru 	if (!indir && !key)
1068961acdeaSSudarsana Reddy Kalluru 		return 0;
1069961acdeaSSudarsana Reddy Kalluru 
1070961acdeaSSudarsana Reddy Kalluru 	if (indir) {
1071961acdeaSSudarsana Reddy Kalluru 		for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1072961acdeaSSudarsana Reddy Kalluru 			edev->rss_params.rss_ind_table[i] = indir[i];
1073961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_INDIR_INITED;
1074961acdeaSSudarsana Reddy Kalluru 	}
1075961acdeaSSudarsana Reddy Kalluru 
1076961acdeaSSudarsana Reddy Kalluru 	if (key) {
1077961acdeaSSudarsana Reddy Kalluru 		memcpy(&edev->rss_params.rss_key, key,
1078961acdeaSSudarsana Reddy Kalluru 		       qede_get_rxfh_key_size(dev));
1079961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_KEY_INITED;
1080961acdeaSSudarsana Reddy Kalluru 	}
1081961acdeaSSudarsana Reddy Kalluru 
1082961acdeaSSudarsana Reddy Kalluru 	if (netif_running(edev->ndev)) {
1083961acdeaSSudarsana Reddy Kalluru 		memset(&vport_update_params, 0, sizeof(vport_update_params));
1084961acdeaSSudarsana Reddy Kalluru 		vport_update_params.update_rss_flg = 1;
1085961acdeaSSudarsana Reddy Kalluru 		vport_update_params.vport_id = 0;
1086961acdeaSSudarsana Reddy Kalluru 		memcpy(&vport_update_params.rss_params, &edev->rss_params,
1087961acdeaSSudarsana Reddy Kalluru 		       sizeof(vport_update_params.rss_params));
1088961acdeaSSudarsana Reddy Kalluru 		return edev->ops->vport_update(edev->cdev,
1089961acdeaSSudarsana Reddy Kalluru 					       &vport_update_params);
1090961acdeaSSudarsana Reddy Kalluru 	}
1091961acdeaSSudarsana Reddy Kalluru 
1092961acdeaSSudarsana Reddy Kalluru 	return 0;
1093961acdeaSSudarsana Reddy Kalluru }
1094961acdeaSSudarsana Reddy Kalluru 
109516f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */
109616f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev)
109716f46bf0SSudarsana Reddy Kalluru {
109816f46bf0SSudarsana Reddy Kalluru 	int i;
109916f46bf0SSudarsana Reddy Kalluru 
110016f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev))
110116f46bf0SSudarsana Reddy Kalluru 		return;
110216f46bf0SSudarsana Reddy Kalluru 
11039a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
110416f46bf0SSudarsana Reddy Kalluru 		/* Update and reenable interrupts */
110516f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1);
110616f46bf0SSudarsana Reddy Kalluru 		napi_enable(&edev->fp_array[i].napi);
110716f46bf0SSudarsana Reddy Kalluru 	}
110816f46bf0SSudarsana Reddy Kalluru }
110916f46bf0SSudarsana Reddy Kalluru 
111016f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */
111116f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev)
111216f46bf0SSudarsana Reddy Kalluru {
111316f46bf0SSudarsana Reddy Kalluru 	int i;
111416f46bf0SSudarsana Reddy Kalluru 
11159a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
111616f46bf0SSudarsana Reddy Kalluru 		napi_disable(&edev->fp_array[i].napi);
111716f46bf0SSudarsana Reddy Kalluru 		/* Disable interrupts */
111816f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0);
111916f46bf0SSudarsana Reddy Kalluru 	}
112016f46bf0SSudarsana Reddy Kalluru }
112116f46bf0SSudarsana Reddy Kalluru 
112216f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev,
112316f46bf0SSudarsana Reddy Kalluru 					  struct sk_buff *skb)
112416f46bf0SSudarsana Reddy Kalluru {
11259a4d7e86SSudarsana Reddy Kalluru 	struct qede_tx_queue *txq = NULL;
112616f46bf0SSudarsana Reddy Kalluru 	struct eth_tx_1st_bd *first_bd;
112716f46bf0SSudarsana Reddy Kalluru 	dma_addr_t mapping;
112816f46bf0SSudarsana Reddy Kalluru 	int i, idx, val;
112916f46bf0SSudarsana Reddy Kalluru 
11309a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
11319a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
11329a4d7e86SSudarsana Reddy Kalluru 			txq = edev->fp_array[i].txqs;
11339a4d7e86SSudarsana Reddy Kalluru 			break;
11349a4d7e86SSudarsana Reddy Kalluru 		}
11359a4d7e86SSudarsana Reddy Kalluru 	}
11369a4d7e86SSudarsana Reddy Kalluru 
11379a4d7e86SSudarsana Reddy Kalluru 	if (!txq) {
11389a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx path is not available\n");
11399a4d7e86SSudarsana Reddy Kalluru 		return -1;
11409a4d7e86SSudarsana Reddy Kalluru 	}
11419a4d7e86SSudarsana Reddy Kalluru 
114216f46bf0SSudarsana Reddy Kalluru 	/* Fill the entry in the SW ring and the BDs in the FW ring */
114316f46bf0SSudarsana Reddy Kalluru 	idx = txq->sw_tx_prod & NUM_TX_BDS_MAX;
114416f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_ring[idx].skb = skb;
114516f46bf0SSudarsana Reddy Kalluru 	first_bd = qed_chain_produce(&txq->tx_pbl);
114616f46bf0SSudarsana Reddy Kalluru 	memset(first_bd, 0, sizeof(*first_bd));
114716f46bf0SSudarsana Reddy Kalluru 	val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
114816f46bf0SSudarsana Reddy Kalluru 	first_bd->data.bd_flags.bitfields = val;
1149351a4dedSYuval Mintz 	val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK;
1150351a4dedSYuval Mintz 	first_bd->data.bitfields |= (val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT);
115116f46bf0SSudarsana Reddy Kalluru 
115216f46bf0SSudarsana Reddy Kalluru 	/* Map skb linear data for DMA and set in the first BD */
115316f46bf0SSudarsana Reddy Kalluru 	mapping = dma_map_single(&edev->pdev->dev, skb->data,
115416f46bf0SSudarsana Reddy Kalluru 				 skb_headlen(skb), DMA_TO_DEVICE);
115516f46bf0SSudarsana Reddy Kalluru 	if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
115616f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "SKB mapping failed\n");
115716f46bf0SSudarsana Reddy Kalluru 		return -ENOMEM;
115816f46bf0SSudarsana Reddy Kalluru 	}
115916f46bf0SSudarsana Reddy Kalluru 	BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb));
116016f46bf0SSudarsana Reddy Kalluru 
116116f46bf0SSudarsana Reddy Kalluru 	/* update the first BD with the actual num BDs */
116216f46bf0SSudarsana Reddy Kalluru 	first_bd->data.nbds = 1;
116316f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_prod++;
116416f46bf0SSudarsana Reddy Kalluru 	/* 'next page' entries are counted in the producer value */
116516f46bf0SSudarsana Reddy Kalluru 	val = cpu_to_le16(qed_chain_get_prod_idx(&txq->tx_pbl));
116616f46bf0SSudarsana Reddy Kalluru 	txq->tx_db.data.bd_prod = val;
116716f46bf0SSudarsana Reddy Kalluru 
116816f46bf0SSudarsana Reddy Kalluru 	/* wmb makes sure that the BDs data is updated before updating the
116916f46bf0SSudarsana Reddy Kalluru 	 * producer, otherwise FW may read old data from the BDs.
117016f46bf0SSudarsana Reddy Kalluru 	 */
117116f46bf0SSudarsana Reddy Kalluru 	wmb();
117216f46bf0SSudarsana Reddy Kalluru 	barrier();
117316f46bf0SSudarsana Reddy Kalluru 	writel(txq->tx_db.raw, txq->doorbell_addr);
117416f46bf0SSudarsana Reddy Kalluru 
117516f46bf0SSudarsana Reddy Kalluru 	/* mmiowb is needed to synchronize doorbell writes from more than one
117616f46bf0SSudarsana Reddy Kalluru 	 * processor. It guarantees that the write arrives to the device before
117716f46bf0SSudarsana Reddy Kalluru 	 * the queue lock is released and another start_xmit is called (possibly
117816f46bf0SSudarsana Reddy Kalluru 	 * on another CPU). Without this barrier, the next doorbell can bypass
117916f46bf0SSudarsana Reddy Kalluru 	 * this doorbell. This is applicable to IA64/Altix systems.
118016f46bf0SSudarsana Reddy Kalluru 	 */
118116f46bf0SSudarsana Reddy Kalluru 	mmiowb();
118216f46bf0SSudarsana Reddy Kalluru 
118316f46bf0SSudarsana Reddy Kalluru 	for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
118416f46bf0SSudarsana Reddy Kalluru 		if (qede_txq_has_work(txq))
118516f46bf0SSudarsana Reddy Kalluru 			break;
118616f46bf0SSudarsana Reddy Kalluru 		usleep_range(100, 200);
118716f46bf0SSudarsana Reddy Kalluru 	}
118816f46bf0SSudarsana Reddy Kalluru 
118916f46bf0SSudarsana Reddy Kalluru 	if (!qede_txq_has_work(txq)) {
119016f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx completion didn't happen\n");
119116f46bf0SSudarsana Reddy Kalluru 		return -1;
119216f46bf0SSudarsana Reddy Kalluru 	}
119316f46bf0SSudarsana Reddy Kalluru 
119416f46bf0SSudarsana Reddy Kalluru 	first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
119516f46bf0SSudarsana Reddy Kalluru 	dma_unmap_page(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
119616f46bf0SSudarsana Reddy Kalluru 		       BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
119716f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_cons++;
119816f46bf0SSudarsana Reddy Kalluru 	txq->sw_tx_ring[idx].skb = NULL;
119916f46bf0SSudarsana Reddy Kalluru 
120016f46bf0SSudarsana Reddy Kalluru 	return 0;
120116f46bf0SSudarsana Reddy Kalluru }
120216f46bf0SSudarsana Reddy Kalluru 
120316f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev)
120416f46bf0SSudarsana Reddy Kalluru {
120516f46bf0SSudarsana Reddy Kalluru 	u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len;
120616f46bf0SSudarsana Reddy Kalluru 	struct eth_fast_path_rx_reg_cqe *fp_cqe;
12079a4d7e86SSudarsana Reddy Kalluru 	struct qede_rx_queue *rxq = NULL;
120816f46bf0SSudarsana Reddy Kalluru 	struct sw_rx_data *sw_rx_data;
120916f46bf0SSudarsana Reddy Kalluru 	union eth_rx_cqe *cqe;
121016f46bf0SSudarsana Reddy Kalluru 	u8 *data_ptr;
121116f46bf0SSudarsana Reddy Kalluru 	int i;
121216f46bf0SSudarsana Reddy Kalluru 
12139a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
12149a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
12159a4d7e86SSudarsana Reddy Kalluru 			rxq = edev->fp_array[i].rxq;
12169a4d7e86SSudarsana Reddy Kalluru 			break;
12179a4d7e86SSudarsana Reddy Kalluru 		}
12189a4d7e86SSudarsana Reddy Kalluru 	}
12199a4d7e86SSudarsana Reddy Kalluru 
12209a4d7e86SSudarsana Reddy Kalluru 	if (!rxq) {
12219a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Rx path is not available\n");
12229a4d7e86SSudarsana Reddy Kalluru 		return -1;
12239a4d7e86SSudarsana Reddy Kalluru 	}
12249a4d7e86SSudarsana Reddy Kalluru 
122516f46bf0SSudarsana Reddy Kalluru 	/* The packet is expected to receive on rx-queue 0 even though RSS is
122616f46bf0SSudarsana Reddy Kalluru 	 * enabled. This is because the queue 0 is configured as the default
122716f46bf0SSudarsana Reddy Kalluru 	 * queue and that the loopback traffic is not IP.
122816f46bf0SSudarsana Reddy Kalluru 	 */
122916f46bf0SSudarsana Reddy Kalluru 	for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
123016f46bf0SSudarsana Reddy Kalluru 		if (qede_has_rx_work(rxq))
123116f46bf0SSudarsana Reddy Kalluru 			break;
123216f46bf0SSudarsana Reddy Kalluru 		usleep_range(100, 200);
123316f46bf0SSudarsana Reddy Kalluru 	}
123416f46bf0SSudarsana Reddy Kalluru 
123516f46bf0SSudarsana Reddy Kalluru 	if (!qede_has_rx_work(rxq)) {
123616f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Failed to receive the traffic\n");
123716f46bf0SSudarsana Reddy Kalluru 		return -1;
123816f46bf0SSudarsana Reddy Kalluru 	}
123916f46bf0SSudarsana Reddy Kalluru 
124016f46bf0SSudarsana Reddy Kalluru 	hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
124116f46bf0SSudarsana Reddy Kalluru 	sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
124216f46bf0SSudarsana Reddy Kalluru 
124316f46bf0SSudarsana Reddy Kalluru 	/* Memory barrier to prevent the CPU from doing speculative reads of CQE
124416f46bf0SSudarsana Reddy Kalluru 	 * / BD before reading hw_comp_cons. If the CQE is read before it is
124516f46bf0SSudarsana Reddy Kalluru 	 * written by FW, then FW writes CQE and SB, and then the CPU reads the
124616f46bf0SSudarsana Reddy Kalluru 	 * hw_comp_cons, it will use an old CQE.
124716f46bf0SSudarsana Reddy Kalluru 	 */
124816f46bf0SSudarsana Reddy Kalluru 	rmb();
124916f46bf0SSudarsana Reddy Kalluru 
125016f46bf0SSudarsana Reddy Kalluru 	/* Get the CQE from the completion ring */
125116f46bf0SSudarsana Reddy Kalluru 	cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring);
125216f46bf0SSudarsana Reddy Kalluru 
125316f46bf0SSudarsana Reddy Kalluru 	/* Get the data from the SW ring */
125416f46bf0SSudarsana Reddy Kalluru 	sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
125516f46bf0SSudarsana Reddy Kalluru 	sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
125616f46bf0SSudarsana Reddy Kalluru 	fp_cqe = &cqe->fast_path_regular;
125716f46bf0SSudarsana Reddy Kalluru 	len =  le16_to_cpu(fp_cqe->len_on_first_bd);
125816f46bf0SSudarsana Reddy Kalluru 	data_ptr = (u8 *)(page_address(sw_rx_data->data) +
125916f46bf0SSudarsana Reddy Kalluru 		     fp_cqe->placement_offset + sw_rx_data->page_offset);
126016f46bf0SSudarsana Reddy Kalluru 	for (i = ETH_HLEN; i < len; i++)
126116f46bf0SSudarsana Reddy Kalluru 		if (data_ptr[i] != (unsigned char)(i & 0xff)) {
126216f46bf0SSudarsana Reddy Kalluru 			DP_NOTICE(edev, "Loopback test failed\n");
126316f46bf0SSudarsana Reddy Kalluru 			qede_recycle_rx_bd_ring(rxq, edev, 1);
126416f46bf0SSudarsana Reddy Kalluru 			return -1;
126516f46bf0SSudarsana Reddy Kalluru 		}
126616f46bf0SSudarsana Reddy Kalluru 
126716f46bf0SSudarsana Reddy Kalluru 	qede_recycle_rx_bd_ring(rxq, edev, 1);
126816f46bf0SSudarsana Reddy Kalluru 
126916f46bf0SSudarsana Reddy Kalluru 	return 0;
127016f46bf0SSudarsana Reddy Kalluru }
127116f46bf0SSudarsana Reddy Kalluru 
127216f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode)
127316f46bf0SSudarsana Reddy Kalluru {
127416f46bf0SSudarsana Reddy Kalluru 	struct qed_link_params link_params;
127516f46bf0SSudarsana Reddy Kalluru 	struct sk_buff *skb = NULL;
127616f46bf0SSudarsana Reddy Kalluru 	int rc = 0, i;
127716f46bf0SSudarsana Reddy Kalluru 	u32 pkt_size;
127816f46bf0SSudarsana Reddy Kalluru 	u8 *packet;
127916f46bf0SSudarsana Reddy Kalluru 
128016f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev)) {
128116f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Interface is down\n");
128216f46bf0SSudarsana Reddy Kalluru 		return -EINVAL;
128316f46bf0SSudarsana Reddy Kalluru 	}
128416f46bf0SSudarsana Reddy Kalluru 
128516f46bf0SSudarsana Reddy Kalluru 	qede_netif_stop(edev);
128616f46bf0SSudarsana Reddy Kalluru 
128716f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Loopback mode */
128816f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
128916f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
129016f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
129116f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = loopback_mode;
129216f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
129316f46bf0SSudarsana Reddy Kalluru 
129416f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
129516f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
129616f46bf0SSudarsana Reddy Kalluru 
129716f46bf0SSudarsana Reddy Kalluru 	/* prepare the loopback packet */
129816f46bf0SSudarsana Reddy Kalluru 	pkt_size = edev->ndev->mtu + ETH_HLEN;
129916f46bf0SSudarsana Reddy Kalluru 
130016f46bf0SSudarsana Reddy Kalluru 	skb = netdev_alloc_skb(edev->ndev, pkt_size);
130116f46bf0SSudarsana Reddy Kalluru 	if (!skb) {
130216f46bf0SSudarsana Reddy Kalluru 		DP_INFO(edev, "Can't allocate skb\n");
130316f46bf0SSudarsana Reddy Kalluru 		rc = -ENOMEM;
130416f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
130516f46bf0SSudarsana Reddy Kalluru 	}
130616f46bf0SSudarsana Reddy Kalluru 	packet = skb_put(skb, pkt_size);
130716f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet, edev->ndev->dev_addr);
130816f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr);
130916f46bf0SSudarsana Reddy Kalluru 	memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN)));
131016f46bf0SSudarsana Reddy Kalluru 	for (i = ETH_HLEN; i < pkt_size; i++)
131116f46bf0SSudarsana Reddy Kalluru 		packet[i] = (unsigned char)(i & 0xff);
131216f46bf0SSudarsana Reddy Kalluru 
131316f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_transmit_traffic(edev, skb);
131416f46bf0SSudarsana Reddy Kalluru 	if (rc)
131516f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
131616f46bf0SSudarsana Reddy Kalluru 
131716f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_receive_traffic(edev);
131816f46bf0SSudarsana Reddy Kalluru 	if (rc)
131916f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
132016f46bf0SSudarsana Reddy Kalluru 
132116f46bf0SSudarsana Reddy Kalluru 	DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n");
132216f46bf0SSudarsana Reddy Kalluru 
132316f46bf0SSudarsana Reddy Kalluru test_loopback_exit:
132416f46bf0SSudarsana Reddy Kalluru 	dev_kfree_skb(skb);
132516f46bf0SSudarsana Reddy Kalluru 
132616f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Normal mode */
132716f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
132816f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
132916f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
133016f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = QED_LINK_LOOPBACK_NONE;
133116f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
133216f46bf0SSudarsana Reddy Kalluru 
133316f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
133416f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
133516f46bf0SSudarsana Reddy Kalluru 
133616f46bf0SSudarsana Reddy Kalluru 	qede_netif_start(edev);
133716f46bf0SSudarsana Reddy Kalluru 
133816f46bf0SSudarsana Reddy Kalluru 	return rc;
133916f46bf0SSudarsana Reddy Kalluru }
134016f46bf0SSudarsana Reddy Kalluru 
13413044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev,
13423044a02eSSudarsana Reddy Kalluru 			   struct ethtool_test *etest, u64 *buf)
13433044a02eSSudarsana Reddy Kalluru {
13443044a02eSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
13453044a02eSSudarsana Reddy Kalluru 
13463044a02eSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
13473044a02eSSudarsana Reddy Kalluru 		   "Self-test command parameters: offline = %d, external_lb = %d\n",
13483044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_OFFLINE),
13493044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2);
13503044a02eSSudarsana Reddy Kalluru 
13513044a02eSSudarsana Reddy Kalluru 	memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX);
13523044a02eSSudarsana Reddy Kalluru 
135316f46bf0SSudarsana Reddy Kalluru 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
135416f46bf0SSudarsana Reddy Kalluru 		if (qede_selftest_run_loopback(edev,
135516f46bf0SSudarsana Reddy Kalluru 					       QED_LINK_LOOPBACK_INT_PHY)) {
135616f46bf0SSudarsana Reddy Kalluru 			buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1;
135716f46bf0SSudarsana Reddy Kalluru 			etest->flags |= ETH_TEST_FL_FAILED;
135816f46bf0SSudarsana Reddy Kalluru 		}
135916f46bf0SSudarsana Reddy Kalluru 	}
136016f46bf0SSudarsana Reddy Kalluru 
13613044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) {
13623044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1;
13633044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
13643044a02eSSudarsana Reddy Kalluru 	}
13653044a02eSSudarsana Reddy Kalluru 
13663044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_memory(edev->cdev)) {
13673044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_MEMORY_TEST] = 1;
13683044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
13693044a02eSSudarsana Reddy Kalluru 	}
13703044a02eSSudarsana Reddy Kalluru 
13713044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_register(edev->cdev)) {
13723044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_REGISTER_TEST] = 1;
13733044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
13743044a02eSSudarsana Reddy Kalluru 	}
13753044a02eSSudarsana Reddy Kalluru 
13763044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_clock(edev->cdev)) {
13773044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_CLOCK_TEST] = 1;
13783044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
13793044a02eSSudarsana Reddy Kalluru 	}
13803044a02eSSudarsana Reddy Kalluru }
13813044a02eSSudarsana Reddy Kalluru 
13823d789994SManish Chopra static int qede_set_tunable(struct net_device *dev,
13833d789994SManish Chopra 			    const struct ethtool_tunable *tuna,
13843d789994SManish Chopra 			    const void *data)
13853d789994SManish Chopra {
13863d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
13873d789994SManish Chopra 	u32 val;
13883d789994SManish Chopra 
13893d789994SManish Chopra 	switch (tuna->id) {
13903d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
13913d789994SManish Chopra 		val = *(u32 *)data;
13923d789994SManish Chopra 		if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) {
13933d789994SManish Chopra 			DP_VERBOSE(edev, QED_MSG_DEBUG,
13943d789994SManish Chopra 				   "Invalid rx copy break value, range is [%u, %u]",
13953d789994SManish Chopra 				   QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE);
13963d789994SManish Chopra 			return -EINVAL;
13973d789994SManish Chopra 		}
13983d789994SManish Chopra 
13993d789994SManish Chopra 		edev->rx_copybreak = *(u32 *)data;
14003d789994SManish Chopra 		break;
14013d789994SManish Chopra 	default:
14023d789994SManish Chopra 		return -EOPNOTSUPP;
14033d789994SManish Chopra 	}
14043d789994SManish Chopra 
14053d789994SManish Chopra 	return 0;
14063d789994SManish Chopra }
14073d789994SManish Chopra 
14083d789994SManish Chopra static int qede_get_tunable(struct net_device *dev,
14093d789994SManish Chopra 			    const struct ethtool_tunable *tuna, void *data)
14103d789994SManish Chopra {
14113d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
14123d789994SManish Chopra 
14133d789994SManish Chopra 	switch (tuna->id) {
14143d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
14153d789994SManish Chopra 		*(u32 *)data = edev->rx_copybreak;
14163d789994SManish Chopra 		break;
14173d789994SManish Chopra 	default:
14183d789994SManish Chopra 		return -EOPNOTSUPP;
14193d789994SManish Chopra 	}
14203d789994SManish Chopra 
14213d789994SManish Chopra 	return 0;
14223d789994SManish Chopra }
14233d789994SManish Chopra 
1424133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = {
1425054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
1426054c67d1SSudarsana Reddy Kalluru 	.set_link_ksettings = qede_set_link_ksettings,
1427133fac0eSSudarsana Kalluru 	.get_drvinfo = qede_get_drvinfo,
1428e0971c83STomer Tayar 	.get_regs_len = qede_get_regs_len,
1429e0971c83STomer Tayar 	.get_regs = qede_get_regs,
1430133fac0eSSudarsana Kalluru 	.get_msglevel = qede_get_msglevel,
1431133fac0eSSudarsana Kalluru 	.set_msglevel = qede_set_msglevel,
143232a7a570SSudarsana Kalluru 	.nway_reset = qede_nway_reset,
1433133fac0eSSudarsana Kalluru 	.get_link = qede_get_link,
1434d552fa84SSudarsana Reddy Kalluru 	.get_coalesce = qede_get_coalesce,
1435d552fa84SSudarsana Reddy Kalluru 	.set_coalesce = qede_set_coalesce,
143601ef7e05SSudarsana Kalluru 	.get_ringparam = qede_get_ringparam,
143701ef7e05SSudarsana Kalluru 	.set_ringparam = qede_set_ringparam,
14380f7db144SSudarsana Kalluru 	.get_pauseparam = qede_get_pauseparam,
14390f7db144SSudarsana Kalluru 	.set_pauseparam = qede_set_pauseparam,
1440133fac0eSSudarsana Kalluru 	.get_strings = qede_get_strings,
14413d971cbdSSudarsana Kalluru 	.set_phys_id = qede_set_phys_id,
1442133fac0eSSudarsana Kalluru 	.get_ethtool_stats = qede_get_ethtool_stats,
1443f3e72109SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
1444133fac0eSSudarsana Kalluru 	.get_sset_count = qede_get_sset_count,
1445961acdeaSSudarsana Reddy Kalluru 	.get_rxnfc = qede_get_rxnfc,
1446961acdeaSSudarsana Reddy Kalluru 	.set_rxnfc = qede_set_rxnfc,
1447961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
1448961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_key_size = qede_get_rxfh_key_size,
1449961acdeaSSudarsana Reddy Kalluru 	.get_rxfh = qede_get_rxfh,
1450961acdeaSSudarsana Reddy Kalluru 	.set_rxfh = qede_set_rxfh,
14518edf049dSSudarsana Kalluru 	.get_channels = qede_get_channels,
14528edf049dSSudarsana Kalluru 	.set_channels = qede_set_channels,
14533044a02eSSudarsana Reddy Kalluru 	.self_test = qede_self_test,
14543d789994SManish Chopra 	.get_tunable = qede_get_tunable,
14553d789994SManish Chopra 	.set_tunable = qede_set_tunable,
1456133fac0eSSudarsana Kalluru };
1457133fac0eSSudarsana Kalluru 
1458fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = {
1459054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
1460fefb0202SYuval Mintz 	.get_drvinfo = qede_get_drvinfo,
1461fefb0202SYuval Mintz 	.get_msglevel = qede_get_msglevel,
1462fefb0202SYuval Mintz 	.set_msglevel = qede_set_msglevel,
1463fefb0202SYuval Mintz 	.get_link = qede_get_link,
1464fefb0202SYuval Mintz 	.get_ringparam = qede_get_ringparam,
1465fefb0202SYuval Mintz 	.set_ringparam = qede_set_ringparam,
1466fefb0202SYuval Mintz 	.get_strings = qede_get_strings,
1467fefb0202SYuval Mintz 	.get_ethtool_stats = qede_get_ethtool_stats,
1468fefb0202SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
1469fefb0202SYuval Mintz 	.get_sset_count = qede_get_sset_count,
1470fefb0202SYuval Mintz 	.get_rxnfc = qede_get_rxnfc,
1471fefb0202SYuval Mintz 	.set_rxnfc = qede_set_rxnfc,
1472fefb0202SYuval Mintz 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
1473fefb0202SYuval Mintz 	.get_rxfh_key_size = qede_get_rxfh_key_size,
1474fefb0202SYuval Mintz 	.get_rxfh = qede_get_rxfh,
1475fefb0202SYuval Mintz 	.set_rxfh = qede_set_rxfh,
1476fefb0202SYuval Mintz 	.get_channels = qede_get_channels,
1477fefb0202SYuval Mintz 	.set_channels = qede_set_channels,
14783d789994SManish Chopra 	.get_tunable = qede_get_tunable,
14793d789994SManish Chopra 	.set_tunable = qede_set_tunable,
1480fefb0202SYuval Mintz };
1481fefb0202SYuval Mintz 
1482133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev)
1483133fac0eSSudarsana Kalluru {
1484fefb0202SYuval Mintz 	struct qede_dev *edev = netdev_priv(dev);
1485fefb0202SYuval Mintz 
1486fefb0202SYuval Mintz 	if (IS_VF(edev))
1487fefb0202SYuval Mintz 		dev->ethtool_ops = &qede_vf_ethtool_ops;
1488fefb0202SYuval Mintz 	else
1489133fac0eSSudarsana Kalluru 		dev->ethtool_ops = &qede_ethtool_ops;
1490133fac0eSSudarsana Kalluru }
1491