1133fac0eSSudarsana Kalluru /* QLogic qede NIC Driver
2e8f1cb50SMintz, Yuval  * Copyright (c) 2015-2017  QLogic Corporation
3133fac0eSSudarsana Kalluru  *
4e8f1cb50SMintz, Yuval  * This software is available to you under a choice of one of two
5e8f1cb50SMintz, Yuval  * licenses.  You may choose to be licensed under the terms of the GNU
6e8f1cb50SMintz, Yuval  * General Public License (GPL) Version 2, available from the file
7e8f1cb50SMintz, Yuval  * COPYING in the main directory of this source tree, or the
8e8f1cb50SMintz, Yuval  * OpenIB.org BSD license below:
9e8f1cb50SMintz, Yuval  *
10e8f1cb50SMintz, Yuval  *     Redistribution and use in source and binary forms, with or
11e8f1cb50SMintz, Yuval  *     without modification, are permitted provided that the following
12e8f1cb50SMintz, Yuval  *     conditions are met:
13e8f1cb50SMintz, Yuval  *
14e8f1cb50SMintz, Yuval  *      - Redistributions of source code must retain the above
15e8f1cb50SMintz, Yuval  *        copyright notice, this list of conditions and the following
16e8f1cb50SMintz, Yuval  *        disclaimer.
17e8f1cb50SMintz, Yuval  *
18e8f1cb50SMintz, Yuval  *      - Redistributions in binary form must reproduce the above
19e8f1cb50SMintz, Yuval  *        copyright notice, this list of conditions and the following
20e8f1cb50SMintz, Yuval  *        disclaimer in the documentation and /or other materials
21e8f1cb50SMintz, Yuval  *        provided with the distribution.
22e8f1cb50SMintz, Yuval  *
23e8f1cb50SMintz, Yuval  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24e8f1cb50SMintz, Yuval  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25e8f1cb50SMintz, Yuval  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26e8f1cb50SMintz, Yuval  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27e8f1cb50SMintz, Yuval  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28e8f1cb50SMintz, Yuval  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29e8f1cb50SMintz, Yuval  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30e8f1cb50SMintz, Yuval  * SOFTWARE.
31133fac0eSSudarsana Kalluru  */
32133fac0eSSudarsana Kalluru #include <linux/version.h>
33133fac0eSSudarsana Kalluru #include <linux/types.h>
34133fac0eSSudarsana Kalluru #include <linux/netdevice.h>
3516f46bf0SSudarsana Reddy Kalluru #include <linux/etherdevice.h>
36133fac0eSSudarsana Kalluru #include <linux/ethtool.h>
37133fac0eSSudarsana Kalluru #include <linux/string.h>
38133fac0eSSudarsana Kalluru #include <linux/pci.h>
39133fac0eSSudarsana Kalluru #include <linux/capability.h>
40f29ffdb6SMintz, Yuval #include <linux/vmalloc.h>
41133fac0eSSudarsana Kalluru #include "qede.h"
424c55215cSSudarsana Reddy Kalluru #include "qede_ptp.h"
43133fac0eSSudarsana Kalluru 
44133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_OFFSET(stat_name) \
45133fac0eSSudarsana Kalluru 	 (offsetof(struct qede_rx_queue, stat_name))
46133fac0eSSudarsana Kalluru #define QEDE_RQSTAT_STRING(stat_name) (#stat_name)
47133fac0eSSudarsana Kalluru #define QEDE_RQSTAT(stat_name) \
48133fac0eSSudarsana Kalluru 	 {QEDE_RQSTAT_OFFSET(stat_name), QEDE_RQSTAT_STRING(stat_name)}
4916f46bf0SSudarsana Reddy Kalluru 
5016f46bf0SSudarsana Reddy Kalluru #define QEDE_SELFTEST_POLL_COUNT 100
5116f46bf0SSudarsana Reddy Kalluru 
52133fac0eSSudarsana Kalluru static const struct {
53133fac0eSSudarsana Kalluru 	u64 offset;
54133fac0eSSudarsana Kalluru 	char string[ETH_GSTRING_LEN];
55133fac0eSSudarsana Kalluru } qede_rqstats_arr[] = {
5668db9ec2SSudarsana Reddy Kalluru 	QEDE_RQSTAT(rcv_pkts),
57133fac0eSSudarsana Kalluru 	QEDE_RQSTAT(rx_hw_errors),
58133fac0eSSudarsana Kalluru 	QEDE_RQSTAT(rx_alloc_errors),
59c72a6125SManish Chopra 	QEDE_RQSTAT(rx_ip_frags),
60496e0517SMintz, Yuval 	QEDE_RQSTAT(xdp_no_pass),
61133fac0eSSudarsana Kalluru };
62133fac0eSSudarsana Kalluru 
63133fac0eSSudarsana Kalluru #define QEDE_NUM_RQSTATS ARRAY_SIZE(qede_rqstats_arr)
6468db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_OFFSET(stat_name) \
6568db9ec2SSudarsana Reddy Kalluru 	(offsetof(struct qede_tx_queue, stat_name))
6668db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT_STRING(stat_name) (#stat_name)
6768db9ec2SSudarsana Reddy Kalluru #define QEDE_TQSTAT(stat_name) \
6868db9ec2SSudarsana Reddy Kalluru 	{QEDE_TQSTAT_OFFSET(stat_name), QEDE_TQSTAT_STRING(stat_name)}
6968db9ec2SSudarsana Reddy Kalluru #define QEDE_NUM_TQSTATS ARRAY_SIZE(qede_tqstats_arr)
7068db9ec2SSudarsana Reddy Kalluru static const struct {
7168db9ec2SSudarsana Reddy Kalluru 	u64 offset;
7268db9ec2SSudarsana Reddy Kalluru 	char string[ETH_GSTRING_LEN];
7368db9ec2SSudarsana Reddy Kalluru } qede_tqstats_arr[] = {
7468db9ec2SSudarsana Reddy Kalluru 	QEDE_TQSTAT(xmit_pkts),
7568db9ec2SSudarsana Reddy Kalluru 	QEDE_TQSTAT(stopped_cnt),
76dcc6abaeSMichael Shteinbok 	QEDE_TQSTAT(tx_mem_alloc_err),
7768db9ec2SSudarsana Reddy Kalluru };
7868db9ec2SSudarsana Reddy Kalluru 
799c79ddaaSMintz, Yuval #define QEDE_STAT_OFFSET(stat_name, type, base) \
809c79ddaaSMintz, Yuval 	(offsetof(type, stat_name) + (base))
814dbcd640SMintz, Yuval #define QEDE_STAT_STRING(stat_name)	(#stat_name)
829c79ddaaSMintz, Yuval #define _QEDE_STAT(stat_name, type, base, attr) \
839c79ddaaSMintz, Yuval 	{QEDE_STAT_OFFSET(stat_name, type, base), \
849c79ddaaSMintz, Yuval 	 QEDE_STAT_STRING(stat_name), \
859c79ddaaSMintz, Yuval 	 attr}
869c79ddaaSMintz, Yuval #define QEDE_STAT(stat_name) \
879c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_common, 0, 0x0)
889c79ddaaSMintz, Yuval #define QEDE_PF_STAT(stat_name) \
899c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_common, 0, \
909c79ddaaSMintz, Yuval 		   BIT(QEDE_STAT_PF_ONLY))
919c79ddaaSMintz, Yuval #define QEDE_PF_BB_STAT(stat_name) \
929c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_bb, \
939c79ddaaSMintz, Yuval 		   offsetof(struct qede_stats, bb), \
949c79ddaaSMintz, Yuval 		   BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_BB_ONLY))
959c79ddaaSMintz, Yuval #define QEDE_PF_AH_STAT(stat_name) \
969c79ddaaSMintz, Yuval 	_QEDE_STAT(stat_name, struct qede_stats_ah, \
979c79ddaaSMintz, Yuval 		   offsetof(struct qede_stats, ah), \
989c79ddaaSMintz, Yuval 		   BIT(QEDE_STAT_PF_ONLY) | BIT(QEDE_STAT_AH_ONLY))
99133fac0eSSudarsana Kalluru static const struct {
100133fac0eSSudarsana Kalluru 	u64 offset;
101133fac0eSSudarsana Kalluru 	char string[ETH_GSTRING_LEN];
1029c79ddaaSMintz, Yuval 	unsigned long attr;
1039c79ddaaSMintz, Yuval #define QEDE_STAT_PF_ONLY	0
1049c79ddaaSMintz, Yuval #define QEDE_STAT_BB_ONLY	1
1059c79ddaaSMintz, Yuval #define QEDE_STAT_AH_ONLY	2
106133fac0eSSudarsana Kalluru } qede_stats_arr[] = {
107133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_ucast_bytes),
108133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_mcast_bytes),
109133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_bcast_bytes),
110133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_ucast_pkts),
111133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_mcast_pkts),
112133fac0eSSudarsana Kalluru 	QEDE_STAT(rx_bcast_pkts),
113133fac0eSSudarsana Kalluru 
114133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_ucast_bytes),
115133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_mcast_bytes),
116133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_bcast_bytes),
117133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_ucast_pkts),
118133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_mcast_pkts),
119133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_bcast_pkts),
120133fac0eSSudarsana Kalluru 
121133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_64_byte_packets),
122d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_65_to_127_byte_packets),
123d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_128_to_255_byte_packets),
124d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_256_to_511_byte_packets),
125d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_512_to_1023_byte_packets),
126d4967cf3SYuval Mintz 	QEDE_PF_STAT(rx_1024_to_1518_byte_packets),
1279c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_1519_to_1522_byte_packets),
1289c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_1519_to_2047_byte_packets),
1299c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_2048_to_4095_byte_packets),
1309c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_4096_to_9216_byte_packets),
1319c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(rx_9217_to_16383_byte_packets),
1329c79ddaaSMintz, Yuval 	QEDE_PF_AH_STAT(rx_1519_to_max_byte_packets),
133133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_64_byte_packets),
134133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_65_to_127_byte_packets),
135133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_128_to_255_byte_packets),
136133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_256_to_511_byte_packets),
137133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_512_to_1023_byte_packets),
138133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_1024_to_1518_byte_packets),
1399c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_1519_to_2047_byte_packets),
1409c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_2048_to_4095_byte_packets),
1419c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_4096_to_9216_byte_packets),
1429c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_9217_to_16383_byte_packets),
1439c79ddaaSMintz, Yuval 	QEDE_PF_AH_STAT(tx_1519_to_max_byte_packets),
144133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_mac_crtl_frames),
145133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_mac_ctrl_frames),
146133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_pause_frames),
147133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_pause_frames),
148133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_pfc_frames),
149133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(tx_pfc_frames),
150133fac0eSSudarsana Kalluru 
151133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_crc_errors),
152133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_align_errors),
153133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_carrier_errors),
154133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_oversize_packets),
155133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_jabbers),
156133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_undersize_packets),
157133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(rx_fragments),
1589c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_lpi_entry_count),
1599c79ddaaSMintz, Yuval 	QEDE_PF_BB_STAT(tx_total_collisions),
160133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(brb_truncates),
161133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(brb_discards),
162133fac0eSSudarsana Kalluru 	QEDE_STAT(no_buff_discards),
163133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(mftag_filter_discards),
164133fac0eSSudarsana Kalluru 	QEDE_PF_STAT(mac_filter_discards),
165608e00d0SManish Chopra 	QEDE_PF_STAT(gft_filter_drop),
166133fac0eSSudarsana Kalluru 	QEDE_STAT(tx_err_drop_pkts),
1671a5a366fSSudarsana Reddy Kalluru 	QEDE_STAT(ttl0_discard),
1681a5a366fSSudarsana Reddy Kalluru 	QEDE_STAT(packet_too_big_discard),
169133fac0eSSudarsana Kalluru 
170133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_pkts),
171133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_events),
172133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_aborts_num),
173133fac0eSSudarsana Kalluru 	QEDE_STAT(non_coalesced_pkts),
174133fac0eSSudarsana Kalluru 	QEDE_STAT(coalesced_bytes),
17532d26a68SSudarsana Reddy Kalluru 
17632d26a68SSudarsana Reddy Kalluru 	QEDE_STAT(link_change_count),
177133fac0eSSudarsana Kalluru };
178133fac0eSSudarsana Kalluru 
179133fac0eSSudarsana Kalluru #define QEDE_NUM_STATS	ARRAY_SIZE(qede_stats_arr)
1809c79ddaaSMintz, Yuval #define QEDE_STAT_IS_PF_ONLY(i) \
1819c79ddaaSMintz, Yuval 	test_bit(QEDE_STAT_PF_ONLY, &qede_stats_arr[i].attr)
1829c79ddaaSMintz, Yuval #define QEDE_STAT_IS_BB_ONLY(i) \
1839c79ddaaSMintz, Yuval 	test_bit(QEDE_STAT_BB_ONLY, &qede_stats_arr[i].attr)
1849c79ddaaSMintz, Yuval #define QEDE_STAT_IS_AH_ONLY(i) \
1859c79ddaaSMintz, Yuval 	test_bit(QEDE_STAT_AH_ONLY, &qede_stats_arr[i].attr)
186133fac0eSSudarsana Kalluru 
187f3e72109SYuval Mintz enum {
188f3e72109SYuval Mintz 	QEDE_PRI_FLAG_CMT,
189f15cff04SSudarsana Reddy Kalluru 	QEDE_PRI_FLAG_SMART_AN_SUPPORT, /* MFW supports SmartAN */
190f3e72109SYuval Mintz 	QEDE_PRI_FLAG_LEN,
191f3e72109SYuval Mintz };
192f3e72109SYuval Mintz 
193f3e72109SYuval Mintz static const char qede_private_arr[QEDE_PRI_FLAG_LEN][ETH_GSTRING_LEN] = {
194f3e72109SYuval Mintz 	"Coupled-Function",
195f15cff04SSudarsana Reddy Kalluru 	"SmartAN capable",
196f3e72109SYuval Mintz };
197f3e72109SYuval Mintz 
1983044a02eSSudarsana Reddy Kalluru enum qede_ethtool_tests {
19916f46bf0SSudarsana Reddy Kalluru 	QEDE_ETHTOOL_INT_LOOPBACK,
2003044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_INTERRUPT_TEST,
2013044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_MEMORY_TEST,
2023044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_REGISTER_TEST,
2033044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_CLOCK_TEST,
2047a4b21b7SMintz, Yuval 	QEDE_ETHTOOL_NVRAM_TEST,
2053044a02eSSudarsana Reddy Kalluru 	QEDE_ETHTOOL_TEST_MAX
2063044a02eSSudarsana Reddy Kalluru };
2073044a02eSSudarsana Reddy Kalluru 
2083044a02eSSudarsana Reddy Kalluru static const char qede_tests_str_arr[QEDE_ETHTOOL_TEST_MAX][ETH_GSTRING_LEN] = {
20916f46bf0SSudarsana Reddy Kalluru 	"Internal loopback (offline)",
2103044a02eSSudarsana Reddy Kalluru 	"Interrupt (online)\t",
2113044a02eSSudarsana Reddy Kalluru 	"Memory (online)\t\t",
2123044a02eSSudarsana Reddy Kalluru 	"Register (online)\t",
2133044a02eSSudarsana Reddy Kalluru 	"Clock (online)\t\t",
2147a4b21b7SMintz, Yuval 	"Nvram (online)\t\t",
2153044a02eSSudarsana Reddy Kalluru };
2163044a02eSSudarsana Reddy Kalluru 
2174dbcd640SMintz, Yuval static void qede_get_strings_stats_txq(struct qede_dev *edev,
2184dbcd640SMintz, Yuval 				       struct qede_tx_queue *txq, u8 **buf)
2194dbcd640SMintz, Yuval {
2204dbcd640SMintz, Yuval 	int i;
2214dbcd640SMintz, Yuval 
2224dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
223cb6aeb07SMintz, Yuval 		if (txq->is_xdp)
224cb6aeb07SMintz, Yuval 			sprintf(*buf, "%d [XDP]: %s",
225cb6aeb07SMintz, Yuval 				QEDE_TXQ_XDP_TO_IDX(edev, txq),
226cb6aeb07SMintz, Yuval 				qede_tqstats_arr[i].string);
227cb6aeb07SMintz, Yuval 		else
2285e7baf0fSManish Chopra 			sprintf(*buf, "%d_%d: %s", txq->index, txq->cos,
2294dbcd640SMintz, Yuval 				qede_tqstats_arr[i].string);
2304dbcd640SMintz, Yuval 		*buf += ETH_GSTRING_LEN;
2314dbcd640SMintz, Yuval 	}
2324dbcd640SMintz, Yuval }
2334dbcd640SMintz, Yuval 
2344dbcd640SMintz, Yuval static void qede_get_strings_stats_rxq(struct qede_dev *edev,
2354dbcd640SMintz, Yuval 				       struct qede_rx_queue *rxq, u8 **buf)
2364dbcd640SMintz, Yuval {
2374dbcd640SMintz, Yuval 	int i;
2384dbcd640SMintz, Yuval 
2394dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
2404dbcd640SMintz, Yuval 		sprintf(*buf, "%d: %s", rxq->rxq_id,
2414dbcd640SMintz, Yuval 			qede_rqstats_arr[i].string);
2424dbcd640SMintz, Yuval 		*buf += ETH_GSTRING_LEN;
2434dbcd640SMintz, Yuval 	}
2444dbcd640SMintz, Yuval }
2454dbcd640SMintz, Yuval 
2469c79ddaaSMintz, Yuval static bool qede_is_irrelevant_stat(struct qede_dev *edev, int stat_index)
2479c79ddaaSMintz, Yuval {
2489c79ddaaSMintz, Yuval 	return (IS_VF(edev) && QEDE_STAT_IS_PF_ONLY(stat_index)) ||
2499c79ddaaSMintz, Yuval 	       (QEDE_IS_BB(edev) && QEDE_STAT_IS_AH_ONLY(stat_index)) ||
2509c79ddaaSMintz, Yuval 	       (QEDE_IS_AH(edev) && QEDE_STAT_IS_BB_ONLY(stat_index));
2519c79ddaaSMintz, Yuval }
2529c79ddaaSMintz, Yuval 
253133fac0eSSudarsana Kalluru static void qede_get_strings_stats(struct qede_dev *edev, u8 *buf)
254133fac0eSSudarsana Kalluru {
2554dbcd640SMintz, Yuval 	struct qede_fastpath *fp;
2564dbcd640SMintz, Yuval 	int i;
257133fac0eSSudarsana Kalluru 
2584dbcd640SMintz, Yuval 	/* Account for queue statistics */
2594dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
2604dbcd640SMintz, Yuval 		fp = &edev->fp_array[i];
26168db9ec2SSudarsana Reddy Kalluru 
2624dbcd640SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_RX)
2634dbcd640SMintz, Yuval 			qede_get_strings_stats_rxq(edev, fp->rxq, &buf);
2644dbcd640SMintz, Yuval 
265cb6aeb07SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_XDP)
266cb6aeb07SMintz, Yuval 			qede_get_strings_stats_txq(edev, fp->xdp_tx, &buf);
267cb6aeb07SMintz, Yuval 
2685e7baf0fSManish Chopra 		if (fp->type & QEDE_FASTPATH_TX) {
2695e7baf0fSManish Chopra 			int cos;
2705e7baf0fSManish Chopra 
2715e7baf0fSManish Chopra 			for_each_cos_in_txq(edev, cos)
2725e7baf0fSManish Chopra 				qede_get_strings_stats_txq(edev,
2735e7baf0fSManish Chopra 							   &fp->txq[cos], &buf);
2745e7baf0fSManish Chopra 		}
275cbbf049aSMintz, Yuval 	}
276cbbf049aSMintz, Yuval 
2774dbcd640SMintz, Yuval 	/* Account for non-queue statistics */
2784dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_STATS; i++) {
2799c79ddaaSMintz, Yuval 		if (qede_is_irrelevant_stat(edev, i))
280fefb0202SYuval Mintz 			continue;
2814dbcd640SMintz, Yuval 		strcpy(buf, qede_stats_arr[i].string);
2824dbcd640SMintz, Yuval 		buf += ETH_GSTRING_LEN;
283133fac0eSSudarsana Kalluru 	}
284133fac0eSSudarsana Kalluru }
285133fac0eSSudarsana Kalluru 
286133fac0eSSudarsana Kalluru static void qede_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
287133fac0eSSudarsana Kalluru {
288133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
289133fac0eSSudarsana Kalluru 
290133fac0eSSudarsana Kalluru 	switch (stringset) {
291133fac0eSSudarsana Kalluru 	case ETH_SS_STATS:
292133fac0eSSudarsana Kalluru 		qede_get_strings_stats(edev, buf);
293133fac0eSSudarsana Kalluru 		break;
294f3e72109SYuval Mintz 	case ETH_SS_PRIV_FLAGS:
295f3e72109SYuval Mintz 		memcpy(buf, qede_private_arr,
296f3e72109SYuval Mintz 		       ETH_GSTRING_LEN * QEDE_PRI_FLAG_LEN);
297f3e72109SYuval Mintz 		break;
2983044a02eSSudarsana Reddy Kalluru 	case ETH_SS_TEST:
2993044a02eSSudarsana Reddy Kalluru 		memcpy(buf, qede_tests_str_arr,
3003044a02eSSudarsana Reddy Kalluru 		       ETH_GSTRING_LEN * QEDE_ETHTOOL_TEST_MAX);
3013044a02eSSudarsana Reddy Kalluru 		break;
302133fac0eSSudarsana Kalluru 	default:
303133fac0eSSudarsana Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
304133fac0eSSudarsana Kalluru 			   "Unsupported stringset 0x%08x\n", stringset);
305133fac0eSSudarsana Kalluru 	}
306133fac0eSSudarsana Kalluru }
307133fac0eSSudarsana Kalluru 
3084dbcd640SMintz, Yuval static void qede_get_ethtool_stats_txq(struct qede_tx_queue *txq, u64 **buf)
3094dbcd640SMintz, Yuval {
3104dbcd640SMintz, Yuval 	int i;
3114dbcd640SMintz, Yuval 
3124dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_TQSTATS; i++) {
3134dbcd640SMintz, Yuval 		**buf = *((u64 *)(((void *)txq) + qede_tqstats_arr[i].offset));
3144dbcd640SMintz, Yuval 		(*buf)++;
3154dbcd640SMintz, Yuval 	}
3164dbcd640SMintz, Yuval }
3174dbcd640SMintz, Yuval 
3184dbcd640SMintz, Yuval static void qede_get_ethtool_stats_rxq(struct qede_rx_queue *rxq, u64 **buf)
3194dbcd640SMintz, Yuval {
3204dbcd640SMintz, Yuval 	int i;
3214dbcd640SMintz, Yuval 
3224dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_RQSTATS; i++) {
3234dbcd640SMintz, Yuval 		**buf = *((u64 *)(((void *)rxq) + qede_rqstats_arr[i].offset));
3244dbcd640SMintz, Yuval 		(*buf)++;
3254dbcd640SMintz, Yuval 	}
3264dbcd640SMintz, Yuval }
3274dbcd640SMintz, Yuval 
328133fac0eSSudarsana Kalluru static void qede_get_ethtool_stats(struct net_device *dev,
329133fac0eSSudarsana Kalluru 				   struct ethtool_stats *stats, u64 *buf)
330133fac0eSSudarsana Kalluru {
331133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
3324dbcd640SMintz, Yuval 	struct qede_fastpath *fp;
3334dbcd640SMintz, Yuval 	int i;
334133fac0eSSudarsana Kalluru 
335133fac0eSSudarsana Kalluru 	qede_fill_by_demand_stats(edev);
336133fac0eSSudarsana Kalluru 
337567b3c12SMintz, Yuval 	/* Need to protect the access to the fastpath array */
338567b3c12SMintz, Yuval 	__qede_lock(edev);
339567b3c12SMintz, Yuval 
3404dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_QUEUE_CNT(edev); i++) {
3414dbcd640SMintz, Yuval 		fp = &edev->fp_array[i];
342133fac0eSSudarsana Kalluru 
3434dbcd640SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_RX)
3444dbcd640SMintz, Yuval 			qede_get_ethtool_stats_rxq(fp->rxq, &buf);
34568db9ec2SSudarsana Reddy Kalluru 
346cb6aeb07SMintz, Yuval 		if (fp->type & QEDE_FASTPATH_XDP)
347cb6aeb07SMintz, Yuval 			qede_get_ethtool_stats_txq(fp->xdp_tx, &buf);
348cb6aeb07SMintz, Yuval 
3495e7baf0fSManish Chopra 		if (fp->type & QEDE_FASTPATH_TX) {
3505e7baf0fSManish Chopra 			int cos;
3515e7baf0fSManish Chopra 
3525e7baf0fSManish Chopra 			for_each_cos_in_txq(edev, cos)
3535e7baf0fSManish Chopra 				qede_get_ethtool_stats_txq(&fp->txq[cos], &buf);
3545e7baf0fSManish Chopra 		}
35568db9ec2SSudarsana Reddy Kalluru 	}
35668db9ec2SSudarsana Reddy Kalluru 
3574dbcd640SMintz, Yuval 	for (i = 0; i < QEDE_NUM_STATS; i++) {
3589c79ddaaSMintz, Yuval 		if (qede_is_irrelevant_stat(edev, i))
359fefb0202SYuval Mintz 			continue;
3604dbcd640SMintz, Yuval 		*buf = *((u64 *)(((void *)&edev->stats) +
3614dbcd640SMintz, Yuval 				 qede_stats_arr[i].offset));
3624dbcd640SMintz, Yuval 
3634dbcd640SMintz, Yuval 		buf++;
364fefb0202SYuval Mintz 	}
365133fac0eSSudarsana Kalluru 
366567b3c12SMintz, Yuval 	__qede_unlock(edev);
367133fac0eSSudarsana Kalluru }
368133fac0eSSudarsana Kalluru 
369133fac0eSSudarsana Kalluru static int qede_get_sset_count(struct net_device *dev, int stringset)
370133fac0eSSudarsana Kalluru {
371133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
3729c79ddaaSMintz, Yuval 	int num_stats = QEDE_NUM_STATS, i;
373133fac0eSSudarsana Kalluru 
374133fac0eSSudarsana Kalluru 	switch (stringset) {
375133fac0eSSudarsana Kalluru 	case ETH_SS_STATS:
376fefb0202SYuval Mintz 		for (i = 0; i < QEDE_NUM_STATS; i++)
3779c79ddaaSMintz, Yuval 			if (qede_is_irrelevant_stat(edev, i))
378fefb0202SYuval Mintz 				num_stats--;
3794dbcd640SMintz, Yuval 
3804dbcd640SMintz, Yuval 		/* Account for the Regular Tx statistics */
3815e7baf0fSManish Chopra 		num_stats += QEDE_TSS_COUNT(edev) * QEDE_NUM_TQSTATS *
3825e7baf0fSManish Chopra 				edev->dev_info.num_tc;
3834dbcd640SMintz, Yuval 
3844dbcd640SMintz, Yuval 		/* Account for the Regular Rx statistics */
3854dbcd640SMintz, Yuval 		num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_RQSTATS;
3864dbcd640SMintz, Yuval 
387cb6aeb07SMintz, Yuval 		/* Account for XDP statistics [if needed] */
388cb6aeb07SMintz, Yuval 		if (edev->xdp_prog)
389cb6aeb07SMintz, Yuval 			num_stats += QEDE_RSS_COUNT(edev) * QEDE_NUM_TQSTATS;
3904dbcd640SMintz, Yuval 		return num_stats;
3914dbcd640SMintz, Yuval 
392f3e72109SYuval Mintz 	case ETH_SS_PRIV_FLAGS:
393f3e72109SYuval Mintz 		return QEDE_PRI_FLAG_LEN;
3943044a02eSSudarsana Reddy Kalluru 	case ETH_SS_TEST:
3956ecb0a0cSYuval Mintz 		if (!IS_VF(edev))
3963044a02eSSudarsana Reddy Kalluru 			return QEDE_ETHTOOL_TEST_MAX;
3976ecb0a0cSYuval Mintz 		else
3986ecb0a0cSYuval Mintz 			return 0;
399133fac0eSSudarsana Kalluru 	default:
400133fac0eSSudarsana Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
401133fac0eSSudarsana Kalluru 			   "Unsupported stringset 0x%08x\n", stringset);
402133fac0eSSudarsana Kalluru 		return -EINVAL;
403133fac0eSSudarsana Kalluru 	}
404133fac0eSSudarsana Kalluru }
405133fac0eSSudarsana Kalluru 
406f3e72109SYuval Mintz static u32 qede_get_priv_flags(struct net_device *dev)
407f3e72109SYuval Mintz {
408f3e72109SYuval Mintz 	struct qede_dev *edev = netdev_priv(dev);
409f15cff04SSudarsana Reddy Kalluru 	u32 flags = 0;
410f3e72109SYuval Mintz 
411f15cff04SSudarsana Reddy Kalluru 	if (edev->dev_info.common.num_hwfns > 1)
412f15cff04SSudarsana Reddy Kalluru 		flags |= BIT(QEDE_PRI_FLAG_CMT);
413f15cff04SSudarsana Reddy Kalluru 
414f15cff04SSudarsana Reddy Kalluru 	if (edev->dev_info.common.smart_an)
415f15cff04SSudarsana Reddy Kalluru 		flags |= BIT(QEDE_PRI_FLAG_SMART_AN_SUPPORT);
416f15cff04SSudarsana Reddy Kalluru 
417f15cff04SSudarsana Reddy Kalluru 	return flags;
418f3e72109SYuval Mintz }
419f3e72109SYuval Mintz 
420054c67d1SSudarsana Reddy Kalluru struct qede_link_mode_mapping {
421054c67d1SSudarsana Reddy Kalluru 	u32 qed_link_mode;
422054c67d1SSudarsana Reddy Kalluru 	u32 ethtool_link_mode;
423054c67d1SSudarsana Reddy Kalluru };
424054c67d1SSudarsana Reddy Kalluru 
425054c67d1SSudarsana Reddy Kalluru static const struct qede_link_mode_mapping qed_lm_map[] = {
426054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Autoneg_BIT, ETHTOOL_LINK_MODE_Autoneg_BIT},
427054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Asym_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT},
428054c67d1SSudarsana Reddy Kalluru 	{QED_LM_Pause_BIT, ETHTOOL_LINK_MODE_Pause_BIT},
429054c67d1SSudarsana Reddy Kalluru 	{QED_LM_1000baseT_Full_BIT, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
430c56a8be7SRahul Verma 	{QED_LM_10000baseT_Full_BIT, ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
431c56a8be7SRahul Verma 	{QED_LM_2500baseX_Full_BIT, ETHTOOL_LINK_MODE_2500baseX_Full_BIT},
432c56a8be7SRahul Verma 	{QED_LM_Backplane_BIT, ETHTOOL_LINK_MODE_Backplane_BIT},
433c56a8be7SRahul Verma 	{QED_LM_1000baseKX_Full_BIT, ETHTOOL_LINK_MODE_1000baseKX_Full_BIT},
434c56a8be7SRahul Verma 	{QED_LM_10000baseKX4_Full_BIT, ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT},
435054c67d1SSudarsana Reddy Kalluru 	{QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
436c56a8be7SRahul Verma 	{QED_LM_10000baseKR_Full_BIT, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT},
437c56a8be7SRahul Verma 	{QED_LM_10000baseR_FEC_BIT, ETHTOOL_LINK_MODE_10000baseR_FEC_BIT},
438631b6707SSudarsana Reddy Kalluru 	{QED_LM_20000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT},
439c56a8be7SRahul Verma 	{QED_LM_40000baseKR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT},
440c56a8be7SRahul Verma 	{QED_LM_40000baseCR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT},
441c56a8be7SRahul Verma 	{QED_LM_40000baseSR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT},
442054c67d1SSudarsana Reddy Kalluru 	{QED_LM_40000baseLR4_Full_BIT, ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT},
443c56a8be7SRahul Verma 	{QED_LM_25000baseCR_Full_BIT, ETHTOOL_LINK_MODE_25000baseCR_Full_BIT},
444c56a8be7SRahul Verma 	{QED_LM_25000baseKR_Full_BIT, ETHTOOL_LINK_MODE_25000baseKR_Full_BIT},
445c56a8be7SRahul Verma 	{QED_LM_25000baseSR_Full_BIT, ETHTOOL_LINK_MODE_25000baseSR_Full_BIT},
446c56a8be7SRahul Verma 	{QED_LM_50000baseCR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT},
447054c67d1SSudarsana Reddy Kalluru 	{QED_LM_50000baseKR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT},
448054c67d1SSudarsana Reddy Kalluru 	{QED_LM_100000baseKR4_Full_BIT,
449054c67d1SSudarsana Reddy Kalluru 		ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT},
450c56a8be7SRahul Verma 	{QED_LM_100000baseSR4_Full_BIT,
451c56a8be7SRahul Verma 		ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT},
452c56a8be7SRahul Verma 	{QED_LM_100000baseCR4_Full_BIT,
453c56a8be7SRahul Verma 		ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT},
454c56a8be7SRahul Verma 	{QED_LM_100000baseLR4_ER4_Full_BIT,
455c56a8be7SRahul Verma 		ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT},
456c56a8be7SRahul Verma 	{QED_LM_50000baseSR2_Full_BIT, ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT},
457c56a8be7SRahul Verma 	{QED_LM_1000baseX_Full_BIT, ETHTOOL_LINK_MODE_1000baseX_Full_BIT},
458c56a8be7SRahul Verma 	{QED_LM_10000baseCR_Full_BIT, ETHTOOL_LINK_MODE_10000baseCR_Full_BIT},
459c56a8be7SRahul Verma 	{QED_LM_10000baseSR_Full_BIT, ETHTOOL_LINK_MODE_10000baseSR_Full_BIT},
460c56a8be7SRahul Verma 	{QED_LM_10000baseLR_Full_BIT, ETHTOOL_LINK_MODE_10000baseLR_Full_BIT},
461c56a8be7SRahul Verma 	{QED_LM_10000baseLRM_Full_BIT, ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT},
462054c67d1SSudarsana Reddy Kalluru };
463054c67d1SSudarsana Reddy Kalluru 
464054c67d1SSudarsana Reddy Kalluru #define QEDE_DRV_TO_ETHTOOL_CAPS(caps, lk_ksettings, name)	\
465054c67d1SSudarsana Reddy Kalluru {								\
466054c67d1SSudarsana Reddy Kalluru 	int i;							\
467054c67d1SSudarsana Reddy Kalluru 								\
468d7455f6eSMintz, Yuval 	for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) {		\
469054c67d1SSudarsana Reddy Kalluru 		if ((caps) & (qed_lm_map[i].qed_link_mode))	\
470054c67d1SSudarsana Reddy Kalluru 			__set_bit(qed_lm_map[i].ethtool_link_mode,\
471054c67d1SSudarsana Reddy Kalluru 				  lk_ksettings->link_modes.name); \
472054c67d1SSudarsana Reddy Kalluru 	}							\
473054c67d1SSudarsana Reddy Kalluru }
474054c67d1SSudarsana Reddy Kalluru 
475054c67d1SSudarsana Reddy Kalluru #define QEDE_ETHTOOL_TO_DRV_CAPS(caps, lk_ksettings, name)	\
476054c67d1SSudarsana Reddy Kalluru {								\
477054c67d1SSudarsana Reddy Kalluru 	int i;							\
478054c67d1SSudarsana Reddy Kalluru 								\
479d7455f6eSMintz, Yuval 	for (i = 0; i < ARRAY_SIZE(qed_lm_map); i++) {		\
480054c67d1SSudarsana Reddy Kalluru 		if (test_bit(qed_lm_map[i].ethtool_link_mode,	\
481054c67d1SSudarsana Reddy Kalluru 			     lk_ksettings->link_modes.name))	\
482054c67d1SSudarsana Reddy Kalluru 			caps |= qed_lm_map[i].qed_link_mode;	\
483054c67d1SSudarsana Reddy Kalluru 	}							\
484054c67d1SSudarsana Reddy Kalluru }
485054c67d1SSudarsana Reddy Kalluru 
486054c67d1SSudarsana Reddy Kalluru static int qede_get_link_ksettings(struct net_device *dev,
487054c67d1SSudarsana Reddy Kalluru 				   struct ethtool_link_ksettings *cmd)
488133fac0eSSudarsana Kalluru {
489054c67d1SSudarsana Reddy Kalluru 	struct ethtool_link_settings *base = &cmd->base;
490133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
491133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
492133fac0eSSudarsana Kalluru 
493567b3c12SMintz, Yuval 	__qede_lock(edev);
494567b3c12SMintz, Yuval 
495133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
496133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
497133fac0eSSudarsana Kalluru 
498054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, supported);
499054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.supported_caps, cmd, supported)
500054c67d1SSudarsana Reddy Kalluru 
501054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, advertising);
502054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.advertised_caps, cmd, advertising)
503054c67d1SSudarsana Reddy Kalluru 
504054c67d1SSudarsana Reddy Kalluru 	ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
505054c67d1SSudarsana Reddy Kalluru 	QEDE_DRV_TO_ETHTOOL_CAPS(current_link.lp_caps, cmd, lp_advertising)
506054c67d1SSudarsana Reddy Kalluru 
507133fac0eSSudarsana Kalluru 	if ((edev->state == QEDE_STATE_OPEN) && (current_link.link_up)) {
508054c67d1SSudarsana Reddy Kalluru 		base->speed = current_link.speed;
509054c67d1SSudarsana Reddy Kalluru 		base->duplex = current_link.duplex;
510133fac0eSSudarsana Kalluru 	} else {
511054c67d1SSudarsana Reddy Kalluru 		base->speed = SPEED_UNKNOWN;
512054c67d1SSudarsana Reddy Kalluru 		base->duplex = DUPLEX_UNKNOWN;
513133fac0eSSudarsana Kalluru 	}
514567b3c12SMintz, Yuval 
515567b3c12SMintz, Yuval 	__qede_unlock(edev);
516567b3c12SMintz, Yuval 
517054c67d1SSudarsana Reddy Kalluru 	base->port = current_link.port;
518054c67d1SSudarsana Reddy Kalluru 	base->autoneg = (current_link.autoneg) ? AUTONEG_ENABLE :
519133fac0eSSudarsana Kalluru 			AUTONEG_DISABLE;
520133fac0eSSudarsana Kalluru 
521133fac0eSSudarsana Kalluru 	return 0;
522133fac0eSSudarsana Kalluru }
523133fac0eSSudarsana Kalluru 
524054c67d1SSudarsana Reddy Kalluru static int qede_set_link_ksettings(struct net_device *dev,
525054c67d1SSudarsana Reddy Kalluru 				   const struct ethtool_link_ksettings *cmd)
526133fac0eSSudarsana Kalluru {
527054c67d1SSudarsana Reddy Kalluru 	const struct ethtool_link_settings *base = &cmd->base;
528133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
529133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
530133fac0eSSudarsana Kalluru 	struct qed_link_params params;
5311e6e2dedSRahul Verma 	u32 sup_caps;
532133fac0eSSudarsana Kalluru 
533fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
534054c67d1SSudarsana Reddy Kalluru 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
535133fac0eSSudarsana Kalluru 		return -EOPNOTSUPP;
536133fac0eSSudarsana Kalluru 	}
537133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
538133fac0eSSudarsana Kalluru 	memset(&params, 0, sizeof(params));
539133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
540133fac0eSSudarsana Kalluru 
541133fac0eSSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_SPEED_ADV_SPEEDS;
542133fac0eSSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_SPEED_AUTONEG;
543054c67d1SSudarsana Reddy Kalluru 	if (base->autoneg == AUTONEG_ENABLE) {
544161adb04Ssudarsana.kalluru@cavium.com 		if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) {
545161adb04Ssudarsana.kalluru@cavium.com 			DP_INFO(edev, "Auto negotiation is not supported\n");
546161adb04Ssudarsana.kalluru@cavium.com 			return -EOPNOTSUPP;
547161adb04Ssudarsana.kalluru@cavium.com 		}
548161adb04Ssudarsana.kalluru@cavium.com 
549133fac0eSSudarsana Kalluru 		params.autoneg = true;
550133fac0eSSudarsana Kalluru 		params.forced_speed = 0;
551054c67d1SSudarsana Reddy Kalluru 		QEDE_ETHTOOL_TO_DRV_CAPS(params.adv_speeds, cmd, advertising)
552133fac0eSSudarsana Kalluru 	} else {		/* forced speed */
553133fac0eSSudarsana Kalluru 		params.override_flags |= QED_LINK_OVERRIDE_SPEED_FORCED_SPEED;
554133fac0eSSudarsana Kalluru 		params.autoneg = false;
555054c67d1SSudarsana Reddy Kalluru 		params.forced_speed = base->speed;
556054c67d1SSudarsana Reddy Kalluru 		switch (base->speed) {
5579ac4c546SSudarsana Reddy Kalluru 		case SPEED_1000:
5581e6e2dedSRahul Verma 			sup_caps = QED_LM_1000baseT_Full_BIT |
5591e6e2dedSRahul Verma 					QED_LM_1000baseKX_Full_BIT |
5601e6e2dedSRahul Verma 					QED_LM_1000baseX_Full_BIT;
5611e6e2dedSRahul Verma 			if (!(current_link.supported_caps & sup_caps)) {
5629ac4c546SSudarsana Reddy Kalluru 				DP_INFO(edev, "1G speed not supported\n");
5639ac4c546SSudarsana Reddy Kalluru 				return -EINVAL;
5649ac4c546SSudarsana Reddy Kalluru 			}
5651e6e2dedSRahul Verma 			params.adv_speeds = current_link.supported_caps &
5661e6e2dedSRahul Verma 						sup_caps;
5679ac4c546SSudarsana Reddy Kalluru 			break;
568133fac0eSSudarsana Kalluru 		case SPEED_10000:
5691e6e2dedSRahul Verma 			sup_caps = QED_LM_10000baseT_Full_BIT |
5701e6e2dedSRahul Verma 					QED_LM_10000baseKR_Full_BIT |
5711e6e2dedSRahul Verma 					QED_LM_10000baseKX4_Full_BIT |
5721e6e2dedSRahul Verma 					QED_LM_10000baseR_FEC_BIT |
5731e6e2dedSRahul Verma 					QED_LM_10000baseCR_Full_BIT |
5741e6e2dedSRahul Verma 					QED_LM_10000baseSR_Full_BIT |
5751e6e2dedSRahul Verma 					QED_LM_10000baseLR_Full_BIT |
5761e6e2dedSRahul Verma 					QED_LM_10000baseLRM_Full_BIT;
5771e6e2dedSRahul Verma 			if (!(current_link.supported_caps & sup_caps)) {
578133fac0eSSudarsana Kalluru 				DP_INFO(edev, "10G speed not supported\n");
579133fac0eSSudarsana Kalluru 				return -EINVAL;
580133fac0eSSudarsana Kalluru 			}
5811e6e2dedSRahul Verma 			params.adv_speeds = current_link.supported_caps &
5821e6e2dedSRahul Verma 						sup_caps;
583054c67d1SSudarsana Reddy Kalluru 			break;
584631b6707SSudarsana Reddy Kalluru 		case SPEED_20000:
585631b6707SSudarsana Reddy Kalluru 			if (!(current_link.supported_caps &
586631b6707SSudarsana Reddy Kalluru 			    QED_LM_20000baseKR2_Full_BIT)) {
587631b6707SSudarsana Reddy Kalluru 				DP_INFO(edev, "20G speed not supported\n");
588631b6707SSudarsana Reddy Kalluru 				return -EINVAL;
589631b6707SSudarsana Reddy Kalluru 			}
590631b6707SSudarsana Reddy Kalluru 			params.adv_speeds = QED_LM_20000baseKR2_Full_BIT;
591631b6707SSudarsana Reddy Kalluru 			break;
592054c67d1SSudarsana Reddy Kalluru 		case SPEED_25000:
5931e6e2dedSRahul Verma 			sup_caps = QED_LM_25000baseKR_Full_BIT |
5941e6e2dedSRahul Verma 					QED_LM_25000baseCR_Full_BIT |
5951e6e2dedSRahul Verma 					QED_LM_25000baseSR_Full_BIT;
5961e6e2dedSRahul Verma 			if (!(current_link.supported_caps & sup_caps)) {
597054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "25G speed not supported\n");
598054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
599054c67d1SSudarsana Reddy Kalluru 			}
6001e6e2dedSRahul Verma 			params.adv_speeds = current_link.supported_caps &
6011e6e2dedSRahul Verma 						sup_caps;
602133fac0eSSudarsana Kalluru 			break;
603133fac0eSSudarsana Kalluru 		case SPEED_40000:
6041e6e2dedSRahul Verma 			sup_caps = QED_LM_40000baseLR4_Full_BIT |
6051e6e2dedSRahul Verma 					QED_LM_40000baseKR4_Full_BIT |
6061e6e2dedSRahul Verma 					QED_LM_40000baseCR4_Full_BIT |
6071e6e2dedSRahul Verma 					QED_LM_40000baseSR4_Full_BIT;
6081e6e2dedSRahul Verma 			if (!(current_link.supported_caps & sup_caps)) {
609133fac0eSSudarsana Kalluru 				DP_INFO(edev, "40G speed not supported\n");
610133fac0eSSudarsana Kalluru 				return -EINVAL;
611133fac0eSSudarsana Kalluru 			}
6121e6e2dedSRahul Verma 			params.adv_speeds = current_link.supported_caps &
6131e6e2dedSRahul Verma 						sup_caps;
614054c67d1SSudarsana Reddy Kalluru 			break;
61516d5946aSYuval Mintz 		case SPEED_50000:
6161e6e2dedSRahul Verma 			sup_caps = QED_LM_50000baseKR2_Full_BIT |
6171e6e2dedSRahul Verma 					QED_LM_50000baseCR2_Full_BIT |
6181e6e2dedSRahul Verma 					QED_LM_50000baseSR2_Full_BIT;
6191e6e2dedSRahul Verma 			if (!(current_link.supported_caps & sup_caps)) {
620054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "50G speed not supported\n");
621054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
622054c67d1SSudarsana Reddy Kalluru 			}
6231e6e2dedSRahul Verma 			params.adv_speeds = current_link.supported_caps &
6241e6e2dedSRahul Verma 						sup_caps;
625054c67d1SSudarsana Reddy Kalluru 			break;
62616d5946aSYuval Mintz 		case SPEED_100000:
6271e6e2dedSRahul Verma 			sup_caps = QED_LM_100000baseKR4_Full_BIT |
6281e6e2dedSRahul Verma 					QED_LM_100000baseSR4_Full_BIT |
6291e6e2dedSRahul Verma 					QED_LM_100000baseCR4_Full_BIT |
6301e6e2dedSRahul Verma 					QED_LM_100000baseLR4_ER4_Full_BIT;
6311e6e2dedSRahul Verma 			if (!(current_link.supported_caps & sup_caps)) {
632054c67d1SSudarsana Reddy Kalluru 				DP_INFO(edev, "100G speed not supported\n");
633054c67d1SSudarsana Reddy Kalluru 				return -EINVAL;
634054c67d1SSudarsana Reddy Kalluru 			}
6351e6e2dedSRahul Verma 			params.adv_speeds = current_link.supported_caps &
6361e6e2dedSRahul Verma 						sup_caps;
637133fac0eSSudarsana Kalluru 			break;
638133fac0eSSudarsana Kalluru 		default:
639054c67d1SSudarsana Reddy Kalluru 			DP_INFO(edev, "Unsupported speed %u\n", base->speed);
640133fac0eSSudarsana Kalluru 			return -EINVAL;
641133fac0eSSudarsana Kalluru 		}
642133fac0eSSudarsana Kalluru 	}
643133fac0eSSudarsana Kalluru 
644133fac0eSSudarsana Kalluru 	params.link_up = true;
645133fac0eSSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
646133fac0eSSudarsana Kalluru 
647133fac0eSSudarsana Kalluru 	return 0;
648133fac0eSSudarsana Kalluru }
649133fac0eSSudarsana Kalluru 
650133fac0eSSudarsana Kalluru static void qede_get_drvinfo(struct net_device *ndev,
651133fac0eSSudarsana Kalluru 			     struct ethtool_drvinfo *info)
652133fac0eSSudarsana Kalluru {
653133fac0eSSudarsana Kalluru 	char mfw[ETHTOOL_FWVERS_LEN], storm[ETHTOOL_FWVERS_LEN];
654133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
655133fac0eSSudarsana Kalluru 
656133fac0eSSudarsana Kalluru 	strlcpy(info->driver, "qede", sizeof(info->driver));
657133fac0eSSudarsana Kalluru 	strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
658133fac0eSSudarsana Kalluru 
659133fac0eSSudarsana Kalluru 	snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
660133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_major,
661133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_minor,
662133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_rev,
663133fac0eSSudarsana Kalluru 		 edev->dev_info.common.fw_eng);
664133fac0eSSudarsana Kalluru 
665133fac0eSSudarsana Kalluru 	snprintf(mfw, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
666133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 24) & 0xFF,
667133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 16) & 0xFF,
668133fac0eSSudarsana Kalluru 		 (edev->dev_info.common.mfw_rev >> 8) & 0xFF,
669133fac0eSSudarsana Kalluru 		 edev->dev_info.common.mfw_rev & 0xFF);
670133fac0eSSudarsana Kalluru 
671133fac0eSSudarsana Kalluru 	if ((strlen(storm) + strlen(mfw) + strlen("mfw storm  ")) <
672133fac0eSSudarsana Kalluru 	    sizeof(info->fw_version)) {
673133fac0eSSudarsana Kalluru 		snprintf(info->fw_version, sizeof(info->fw_version),
674133fac0eSSudarsana Kalluru 			 "mfw %s storm %s", mfw, storm);
675133fac0eSSudarsana Kalluru 	} else {
676133fac0eSSudarsana Kalluru 		snprintf(info->fw_version, sizeof(info->fw_version),
677133fac0eSSudarsana Kalluru 			 "%s %s", mfw, storm);
678133fac0eSSudarsana Kalluru 	}
679133fac0eSSudarsana Kalluru 
680133fac0eSSudarsana Kalluru 	strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
681133fac0eSSudarsana Kalluru }
682133fac0eSSudarsana Kalluru 
68314d39648SMintz, Yuval static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
68414d39648SMintz, Yuval {
68514d39648SMintz, Yuval 	struct qede_dev *edev = netdev_priv(ndev);
68614d39648SMintz, Yuval 
68714d39648SMintz, Yuval 	if (edev->dev_info.common.wol_support) {
68814d39648SMintz, Yuval 		wol->supported = WAKE_MAGIC;
68914d39648SMintz, Yuval 		wol->wolopts = edev->wol_enabled ? WAKE_MAGIC : 0;
69014d39648SMintz, Yuval 	}
69114d39648SMintz, Yuval }
69214d39648SMintz, Yuval 
69314d39648SMintz, Yuval static int qede_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
69414d39648SMintz, Yuval {
69514d39648SMintz, Yuval 	struct qede_dev *edev = netdev_priv(ndev);
69614d39648SMintz, Yuval 	bool wol_requested;
69714d39648SMintz, Yuval 	int rc;
69814d39648SMintz, Yuval 
69914d39648SMintz, Yuval 	if (wol->wolopts & ~WAKE_MAGIC) {
70014d39648SMintz, Yuval 		DP_INFO(edev,
70114d39648SMintz, Yuval 			"Can't support WoL options other than magic-packet\n");
70214d39648SMintz, Yuval 		return -EINVAL;
70314d39648SMintz, Yuval 	}
70414d39648SMintz, Yuval 
70514d39648SMintz, Yuval 	wol_requested = !!(wol->wolopts & WAKE_MAGIC);
70614d39648SMintz, Yuval 	if (wol_requested == edev->wol_enabled)
70714d39648SMintz, Yuval 		return 0;
70814d39648SMintz, Yuval 
70914d39648SMintz, Yuval 	/* Need to actually change configuration */
71014d39648SMintz, Yuval 	if (!edev->dev_info.common.wol_support) {
71114d39648SMintz, Yuval 		DP_INFO(edev, "Device doesn't support WoL\n");
71214d39648SMintz, Yuval 		return -EINVAL;
71314d39648SMintz, Yuval 	}
71414d39648SMintz, Yuval 
71514d39648SMintz, Yuval 	rc = edev->ops->common->update_wol(edev->cdev, wol_requested);
71614d39648SMintz, Yuval 	if (!rc)
71714d39648SMintz, Yuval 		edev->wol_enabled = wol_requested;
71814d39648SMintz, Yuval 
71914d39648SMintz, Yuval 	return rc;
72014d39648SMintz, Yuval }
72114d39648SMintz, Yuval 
722133fac0eSSudarsana Kalluru static u32 qede_get_msglevel(struct net_device *ndev)
723133fac0eSSudarsana Kalluru {
724133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
725133fac0eSSudarsana Kalluru 
7261a635e48SYuval Mintz 	return ((u32)edev->dp_level << QED_LOG_LEVEL_SHIFT) | edev->dp_module;
727133fac0eSSudarsana Kalluru }
728133fac0eSSudarsana Kalluru 
729133fac0eSSudarsana Kalluru static void qede_set_msglevel(struct net_device *ndev, u32 level)
730133fac0eSSudarsana Kalluru {
731133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
732133fac0eSSudarsana Kalluru 	u32 dp_module = 0;
733133fac0eSSudarsana Kalluru 	u8 dp_level = 0;
734133fac0eSSudarsana Kalluru 
735133fac0eSSudarsana Kalluru 	qede_config_debug(level, &dp_module, &dp_level);
736133fac0eSSudarsana Kalluru 
737133fac0eSSudarsana Kalluru 	edev->dp_level = dp_level;
738133fac0eSSudarsana Kalluru 	edev->dp_module = dp_module;
739133fac0eSSudarsana Kalluru 	edev->ops->common->update_msglvl(edev->cdev,
740133fac0eSSudarsana Kalluru 					 dp_module, dp_level);
741133fac0eSSudarsana Kalluru }
742133fac0eSSudarsana Kalluru 
74332a7a570SSudarsana Kalluru static int qede_nway_reset(struct net_device *dev)
74432a7a570SSudarsana Kalluru {
74532a7a570SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
74632a7a570SSudarsana Kalluru 	struct qed_link_output current_link;
74732a7a570SSudarsana Kalluru 	struct qed_link_params link_params;
74832a7a570SSudarsana Kalluru 
749fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
7501a635e48SYuval Mintz 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
751fe7cd2bfSYuval Mintz 		return -EOPNOTSUPP;
752fe7cd2bfSYuval Mintz 	}
753fe7cd2bfSYuval Mintz 
75432a7a570SSudarsana Kalluru 	if (!netif_running(dev))
75532a7a570SSudarsana Kalluru 		return 0;
75632a7a570SSudarsana Kalluru 
75732a7a570SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
75832a7a570SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
75932a7a570SSudarsana Kalluru 	if (!current_link.link_up)
76032a7a570SSudarsana Kalluru 		return 0;
76132a7a570SSudarsana Kalluru 
76232a7a570SSudarsana Kalluru 	/* Toggle the link */
76332a7a570SSudarsana Kalluru 	memset(&link_params, 0, sizeof(link_params));
76432a7a570SSudarsana Kalluru 	link_params.link_up = false;
76532a7a570SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
76632a7a570SSudarsana Kalluru 	link_params.link_up = true;
76732a7a570SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
76832a7a570SSudarsana Kalluru 
76932a7a570SSudarsana Kalluru 	return 0;
77032a7a570SSudarsana Kalluru }
77132a7a570SSudarsana Kalluru 
772133fac0eSSudarsana Kalluru static u32 qede_get_link(struct net_device *dev)
773133fac0eSSudarsana Kalluru {
774133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
775133fac0eSSudarsana Kalluru 	struct qed_link_output current_link;
776133fac0eSSudarsana Kalluru 
777133fac0eSSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
778133fac0eSSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
779133fac0eSSudarsana Kalluru 
780133fac0eSSudarsana Kalluru 	return current_link.link_up;
781133fac0eSSudarsana Kalluru }
782133fac0eSSudarsana Kalluru 
783ccfa110cSSudarsana Reddy Kalluru static int qede_flash_device(struct net_device *dev,
784ccfa110cSSudarsana Reddy Kalluru 			     struct ethtool_flash *flash)
785ccfa110cSSudarsana Reddy Kalluru {
786ccfa110cSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
787ccfa110cSSudarsana Reddy Kalluru 
788ccfa110cSSudarsana Reddy Kalluru 	return edev->ops->common->nvm_flash(edev->cdev, flash->data);
789ccfa110cSSudarsana Reddy Kalluru }
790ccfa110cSSudarsana Reddy Kalluru 
791d552fa84SSudarsana Reddy Kalluru static int qede_get_coalesce(struct net_device *dev,
792d552fa84SSudarsana Reddy Kalluru 			     struct ethtool_coalesce *coal)
793d552fa84SSudarsana Reddy Kalluru {
794bf5a94bfSRahul Verma 	void *rx_handle = NULL, *tx_handle = NULL;
795d552fa84SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
796bf5a94bfSRahul Verma 	u16 rx_coal, tx_coal, i, rc = 0;
797bf5a94bfSRahul Verma 	struct qede_fastpath *fp;
798bf5a94bfSRahul Verma 
799bf5a94bfSRahul Verma 	rx_coal = QED_DEFAULT_RX_USECS;
800bf5a94bfSRahul Verma 	tx_coal = QED_DEFAULT_TX_USECS;
801d552fa84SSudarsana Reddy Kalluru 
802d552fa84SSudarsana Reddy Kalluru 	memset(coal, 0, sizeof(struct ethtool_coalesce));
803d2890deaSSudarsana Reddy Kalluru 
804bf5a94bfSRahul Verma 	__qede_lock(edev);
805bf5a94bfSRahul Verma 	if (edev->state == QEDE_STATE_OPEN) {
806bf5a94bfSRahul Verma 		for_each_queue(i) {
807bf5a94bfSRahul Verma 			fp = &edev->fp_array[i];
808d552fa84SSudarsana Reddy Kalluru 
809bf5a94bfSRahul Verma 			if (fp->type & QEDE_FASTPATH_RX) {
810bf5a94bfSRahul Verma 				rx_handle = fp->rxq->handle;
811bf5a94bfSRahul Verma 				break;
812bf5a94bfSRahul Verma 			}
813bf5a94bfSRahul Verma 		}
814bf5a94bfSRahul Verma 
815bf5a94bfSRahul Verma 		rc = edev->ops->get_coalesce(edev->cdev, &rx_coal, rx_handle);
816bf5a94bfSRahul Verma 		if (rc) {
817bf5a94bfSRahul Verma 			DP_INFO(edev, "Read Rx coalesce error\n");
818bf5a94bfSRahul Verma 			goto out;
819bf5a94bfSRahul Verma 		}
820bf5a94bfSRahul Verma 
821bf5a94bfSRahul Verma 		for_each_queue(i) {
8225e7baf0fSManish Chopra 			struct qede_tx_queue *txq;
8235e7baf0fSManish Chopra 
824bf5a94bfSRahul Verma 			fp = &edev->fp_array[i];
8255e7baf0fSManish Chopra 
8265e7baf0fSManish Chopra 			/* All TX queues of given fastpath uses same
8275e7baf0fSManish Chopra 			 * coalescing value, so no need to iterate over
8285e7baf0fSManish Chopra 			 * all TCs, TC0 txq should suffice.
8295e7baf0fSManish Chopra 			 */
830bf5a94bfSRahul Verma 			if (fp->type & QEDE_FASTPATH_TX) {
8315e7baf0fSManish Chopra 				txq = QEDE_FP_TC0_TXQ(fp);
8325e7baf0fSManish Chopra 				tx_handle = txq->handle;
833bf5a94bfSRahul Verma 				break;
834bf5a94bfSRahul Verma 			}
835bf5a94bfSRahul Verma 		}
836bf5a94bfSRahul Verma 
837bf5a94bfSRahul Verma 		rc = edev->ops->get_coalesce(edev->cdev, &tx_coal, tx_handle);
838bf5a94bfSRahul Verma 		if (rc)
839bf5a94bfSRahul Verma 			DP_INFO(edev, "Read Tx coalesce error\n");
840bf5a94bfSRahul Verma 	}
841bf5a94bfSRahul Verma 
842bf5a94bfSRahul Verma out:
843bf5a94bfSRahul Verma 	__qede_unlock(edev);
844bf5a94bfSRahul Verma 
845bf5a94bfSRahul Verma 	coal->rx_coalesce_usecs = rx_coal;
846bf5a94bfSRahul Verma 	coal->tx_coalesce_usecs = tx_coal;
847bf5a94bfSRahul Verma 
848bf5a94bfSRahul Verma 	return rc;
849d552fa84SSudarsana Reddy Kalluru }
850d552fa84SSudarsana Reddy Kalluru 
851d552fa84SSudarsana Reddy Kalluru static int qede_set_coalesce(struct net_device *dev,
852d552fa84SSudarsana Reddy Kalluru 			     struct ethtool_coalesce *coal)
853d552fa84SSudarsana Reddy Kalluru {
854d552fa84SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
855477f2d14SRahul Verma 	struct qede_fastpath *fp;
856d552fa84SSudarsana Reddy Kalluru 	int i, rc = 0;
857477f2d14SRahul Verma 	u16 rxc, txc;
858d552fa84SSudarsana Reddy Kalluru 
859d552fa84SSudarsana Reddy Kalluru 	if (!netif_running(dev)) {
860d552fa84SSudarsana Reddy Kalluru 		DP_INFO(edev, "Interface is down\n");
861d552fa84SSudarsana Reddy Kalluru 		return -EINVAL;
862d552fa84SSudarsana Reddy Kalluru 	}
863d552fa84SSudarsana Reddy Kalluru 
864d552fa84SSudarsana Reddy Kalluru 	if (coal->rx_coalesce_usecs > QED_COALESCE_MAX ||
865d552fa84SSudarsana Reddy Kalluru 	    coal->tx_coalesce_usecs > QED_COALESCE_MAX) {
866d552fa84SSudarsana Reddy Kalluru 		DP_INFO(edev,
867d552fa84SSudarsana Reddy Kalluru 			"Can't support requested %s coalesce value [max supported value %d]\n",
868477f2d14SRahul Verma 			coal->rx_coalesce_usecs > QED_COALESCE_MAX ? "rx" :
869477f2d14SRahul Verma 			"tx", QED_COALESCE_MAX);
870d552fa84SSudarsana Reddy Kalluru 		return -EINVAL;
871d552fa84SSudarsana Reddy Kalluru 	}
872d552fa84SSudarsana Reddy Kalluru 
873d552fa84SSudarsana Reddy Kalluru 	rxc = (u16)coal->rx_coalesce_usecs;
874d552fa84SSudarsana Reddy Kalluru 	txc = (u16)coal->tx_coalesce_usecs;
8759a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
876477f2d14SRahul Verma 		fp = &edev->fp_array[i];
877477f2d14SRahul Verma 
878477f2d14SRahul Verma 		if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
879477f2d14SRahul Verma 			rc = edev->ops->common->set_coalesce(edev->cdev,
880477f2d14SRahul Verma 							     rxc, 0,
881477f2d14SRahul Verma 							     fp->rxq->handle);
882d552fa84SSudarsana Reddy Kalluru 			if (rc) {
883477f2d14SRahul Verma 				DP_INFO(edev,
884477f2d14SRahul Verma 					"Set RX coalesce error, rc = %d\n", rc);
885d552fa84SSudarsana Reddy Kalluru 				return rc;
886d552fa84SSudarsana Reddy Kalluru 			}
887d552fa84SSudarsana Reddy Kalluru 		}
888d552fa84SSudarsana Reddy Kalluru 
889477f2d14SRahul Verma 		if (edev->fp_array[i].type & QEDE_FASTPATH_TX) {
8905e7baf0fSManish Chopra 			struct qede_tx_queue *txq;
8915e7baf0fSManish Chopra 
8925e7baf0fSManish Chopra 			/* All TX queues of given fastpath uses same
8935e7baf0fSManish Chopra 			 * coalescing value, so no need to iterate over
8945e7baf0fSManish Chopra 			 * all TCs, TC0 txq should suffice.
8955e7baf0fSManish Chopra 			 */
8965e7baf0fSManish Chopra 			txq = QEDE_FP_TC0_TXQ(fp);
8975e7baf0fSManish Chopra 
898477f2d14SRahul Verma 			rc = edev->ops->common->set_coalesce(edev->cdev,
899477f2d14SRahul Verma 							     0, txc,
9005e7baf0fSManish Chopra 							     txq->handle);
901477f2d14SRahul Verma 			if (rc) {
902477f2d14SRahul Verma 				DP_INFO(edev,
903477f2d14SRahul Verma 					"Set TX coalesce error, rc = %d\n", rc);
904477f2d14SRahul Verma 				return rc;
905477f2d14SRahul Verma 			}
906477f2d14SRahul Verma 		}
907477f2d14SRahul Verma 	}
908477f2d14SRahul Verma 
909d552fa84SSudarsana Reddy Kalluru 	return rc;
910d552fa84SSudarsana Reddy Kalluru }
911d552fa84SSudarsana Reddy Kalluru 
91201ef7e05SSudarsana Kalluru static void qede_get_ringparam(struct net_device *dev,
91301ef7e05SSudarsana Kalluru 			       struct ethtool_ringparam *ering)
91401ef7e05SSudarsana Kalluru {
91501ef7e05SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
91601ef7e05SSudarsana Kalluru 
91701ef7e05SSudarsana Kalluru 	ering->rx_max_pending = NUM_RX_BDS_MAX;
91801ef7e05SSudarsana Kalluru 	ering->rx_pending = edev->q_num_rx_buffers;
91901ef7e05SSudarsana Kalluru 	ering->tx_max_pending = NUM_TX_BDS_MAX;
92001ef7e05SSudarsana Kalluru 	ering->tx_pending = edev->q_num_tx_buffers;
92101ef7e05SSudarsana Kalluru }
92201ef7e05SSudarsana Kalluru 
92301ef7e05SSudarsana Kalluru static int qede_set_ringparam(struct net_device *dev,
92401ef7e05SSudarsana Kalluru 			      struct ethtool_ringparam *ering)
92501ef7e05SSudarsana Kalluru {
92601ef7e05SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
92701ef7e05SSudarsana Kalluru 
92801ef7e05SSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
92901ef7e05SSudarsana Kalluru 		   "Set ring params command parameters: rx_pending = %d, tx_pending = %d\n",
93001ef7e05SSudarsana Kalluru 		   ering->rx_pending, ering->tx_pending);
93101ef7e05SSudarsana Kalluru 
93201ef7e05SSudarsana Kalluru 	/* Validate legality of configuration */
93301ef7e05SSudarsana Kalluru 	if (ering->rx_pending > NUM_RX_BDS_MAX ||
93401ef7e05SSudarsana Kalluru 	    ering->rx_pending < NUM_RX_BDS_MIN ||
93501ef7e05SSudarsana Kalluru 	    ering->tx_pending > NUM_TX_BDS_MAX ||
93601ef7e05SSudarsana Kalluru 	    ering->tx_pending < NUM_TX_BDS_MIN) {
93701ef7e05SSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
93801ef7e05SSudarsana Kalluru 			   "Can only support Rx Buffer size [0%08x,...,0x%08x] and Tx Buffer size [0x%08x,...,0x%08x]\n",
93901ef7e05SSudarsana Kalluru 			   NUM_RX_BDS_MIN, NUM_RX_BDS_MAX,
94001ef7e05SSudarsana Kalluru 			   NUM_TX_BDS_MIN, NUM_TX_BDS_MAX);
94101ef7e05SSudarsana Kalluru 		return -EINVAL;
94201ef7e05SSudarsana Kalluru 	}
94301ef7e05SSudarsana Kalluru 
94401ef7e05SSudarsana Kalluru 	/* Change ring size and re-load */
94501ef7e05SSudarsana Kalluru 	edev->q_num_rx_buffers = ering->rx_pending;
94601ef7e05SSudarsana Kalluru 	edev->q_num_tx_buffers = ering->tx_pending;
94701ef7e05SSudarsana Kalluru 
948567b3c12SMintz, Yuval 	qede_reload(edev, NULL, false);
94901ef7e05SSudarsana Kalluru 
95001ef7e05SSudarsana Kalluru 	return 0;
95101ef7e05SSudarsana Kalluru }
95201ef7e05SSudarsana Kalluru 
9530f7db144SSudarsana Kalluru static void qede_get_pauseparam(struct net_device *dev,
9540f7db144SSudarsana Kalluru 				struct ethtool_pauseparam *epause)
9550f7db144SSudarsana Kalluru {
9560f7db144SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
9570f7db144SSudarsana Kalluru 	struct qed_link_output current_link;
9580f7db144SSudarsana Kalluru 
9590f7db144SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
9600f7db144SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
9610f7db144SSudarsana Kalluru 
9620f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_AUTONEG_ENABLE)
9630f7db144SSudarsana Kalluru 		epause->autoneg = true;
9640f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_RX_ENABLE)
9650f7db144SSudarsana Kalluru 		epause->rx_pause = true;
9660f7db144SSudarsana Kalluru 	if (current_link.pause_config & QED_LINK_PAUSE_TX_ENABLE)
9670f7db144SSudarsana Kalluru 		epause->tx_pause = true;
9680f7db144SSudarsana Kalluru 
9690f7db144SSudarsana Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
9700f7db144SSudarsana Kalluru 		   "ethtool_pauseparam: cmd %d  autoneg %d  rx_pause %d  tx_pause %d\n",
9710f7db144SSudarsana Kalluru 		   epause->cmd, epause->autoneg, epause->rx_pause,
9720f7db144SSudarsana Kalluru 		   epause->tx_pause);
9730f7db144SSudarsana Kalluru }
9740f7db144SSudarsana Kalluru 
9750f7db144SSudarsana Kalluru static int qede_set_pauseparam(struct net_device *dev,
9760f7db144SSudarsana Kalluru 			       struct ethtool_pauseparam *epause)
9770f7db144SSudarsana Kalluru {
9780f7db144SSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
9790f7db144SSudarsana Kalluru 	struct qed_link_params params;
9800f7db144SSudarsana Kalluru 	struct qed_link_output current_link;
9810f7db144SSudarsana Kalluru 
982fe7cd2bfSYuval Mintz 	if (!edev->ops || !edev->ops->common->can_link_change(edev->cdev)) {
9830f7db144SSudarsana Kalluru 		DP_INFO(edev,
984fe7cd2bfSYuval Mintz 			"Pause settings are not allowed to be changed\n");
9850f7db144SSudarsana Kalluru 		return -EOPNOTSUPP;
9860f7db144SSudarsana Kalluru 	}
9870f7db144SSudarsana Kalluru 
9880f7db144SSudarsana Kalluru 	memset(&current_link, 0, sizeof(current_link));
9890f7db144SSudarsana Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
9900f7db144SSudarsana Kalluru 
9910f7db144SSudarsana Kalluru 	memset(&params, 0, sizeof(params));
9920f7db144SSudarsana Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_PAUSE_CONFIG;
9930f7db144SSudarsana Kalluru 	if (epause->autoneg) {
994d194fd26SYuval Mintz 		if (!(current_link.supported_caps & QED_LM_Autoneg_BIT)) {
9950f7db144SSudarsana Kalluru 			DP_INFO(edev, "autoneg not supported\n");
9960f7db144SSudarsana Kalluru 			return -EINVAL;
9970f7db144SSudarsana Kalluru 		}
9980f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_AUTONEG_ENABLE;
9990f7db144SSudarsana Kalluru 	}
10000f7db144SSudarsana Kalluru 	if (epause->rx_pause)
10010f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_RX_ENABLE;
10020f7db144SSudarsana Kalluru 	if (epause->tx_pause)
10030f7db144SSudarsana Kalluru 		params.pause_config |= QED_LINK_PAUSE_TX_ENABLE;
10040f7db144SSudarsana Kalluru 
10050f7db144SSudarsana Kalluru 	params.link_up = true;
10060f7db144SSudarsana Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
10070f7db144SSudarsana Kalluru 
10080f7db144SSudarsana Kalluru 	return 0;
10090f7db144SSudarsana Kalluru }
10100f7db144SSudarsana Kalluru 
1011e0971c83STomer Tayar static void qede_get_regs(struct net_device *ndev,
1012e0971c83STomer Tayar 			  struct ethtool_regs *regs, void *buffer)
1013e0971c83STomer Tayar {
1014e0971c83STomer Tayar 	struct qede_dev *edev = netdev_priv(ndev);
1015e0971c83STomer Tayar 
1016e0971c83STomer Tayar 	regs->version = 0;
1017e0971c83STomer Tayar 	memset(buffer, 0, regs->len);
1018e0971c83STomer Tayar 
1019e0971c83STomer Tayar 	if (edev->ops && edev->ops->common)
1020e0971c83STomer Tayar 		edev->ops->common->dbg_all_data(edev->cdev, buffer);
1021e0971c83STomer Tayar }
1022e0971c83STomer Tayar 
1023e0971c83STomer Tayar static int qede_get_regs_len(struct net_device *ndev)
1024e0971c83STomer Tayar {
1025e0971c83STomer Tayar 	struct qede_dev *edev = netdev_priv(ndev);
1026e0971c83STomer Tayar 
1027e0971c83STomer Tayar 	if (edev->ops && edev->ops->common)
1028e0971c83STomer Tayar 		return edev->ops->common->dbg_all_data_size(edev->cdev);
1029e0971c83STomer Tayar 	else
1030e0971c83STomer Tayar 		return -EINVAL;
1031e0971c83STomer Tayar }
1032e0971c83STomer Tayar 
1033567b3c12SMintz, Yuval static void qede_update_mtu(struct qede_dev *edev,
1034567b3c12SMintz, Yuval 			    struct qede_reload_args *args)
1035133fac0eSSudarsana Kalluru {
1036567b3c12SMintz, Yuval 	edev->ndev->mtu = args->u.mtu;
1037133fac0eSSudarsana Kalluru }
1038133fac0eSSudarsana Kalluru 
1039133fac0eSSudarsana Kalluru /* Netdevice NDOs */
1040133fac0eSSudarsana Kalluru int qede_change_mtu(struct net_device *ndev, int new_mtu)
1041133fac0eSSudarsana Kalluru {
1042133fac0eSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(ndev);
1043567b3c12SMintz, Yuval 	struct qede_reload_args args;
1044133fac0eSSudarsana Kalluru 
1045133fac0eSSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
1046133fac0eSSudarsana Kalluru 		   "Configuring MTU size of %d\n", new_mtu);
1047133fac0eSSudarsana Kalluru 
104818c602deSMichael Chan 	if (new_mtu > PAGE_SIZE)
104918c602deSMichael Chan 		ndev->features &= ~NETIF_F_GRO_HW;
105018c602deSMichael Chan 
1051133fac0eSSudarsana Kalluru 	/* Set the mtu field and re-start the interface if needed */
1052567b3c12SMintz, Yuval 	args.u.mtu = new_mtu;
1053567b3c12SMintz, Yuval 	args.func = &qede_update_mtu;
1054567b3c12SMintz, Yuval 	qede_reload(edev, &args, false);
1055133fac0eSSudarsana Kalluru 
1056567b3c12SMintz, Yuval 	edev->ops->common->update_mtu(edev->cdev, new_mtu);
10570fefbfbaSSudarsana Kalluru 
1058133fac0eSSudarsana Kalluru 	return 0;
1059133fac0eSSudarsana Kalluru }
1060133fac0eSSudarsana Kalluru 
10618edf049dSSudarsana Kalluru static void qede_get_channels(struct net_device *dev,
10628edf049dSSudarsana Kalluru 			      struct ethtool_channels *channels)
10638edf049dSSudarsana Kalluru {
10648edf049dSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
10658edf049dSSudarsana Kalluru 
10668edf049dSSudarsana Kalluru 	channels->max_combined = QEDE_MAX_RSS_CNT(edev);
1067bdc8cbd3SSudarsana Reddy Kalluru 	channels->max_rx = QEDE_MAX_RSS_CNT(edev);
1068bdc8cbd3SSudarsana Reddy Kalluru 	channels->max_tx = QEDE_MAX_RSS_CNT(edev);
10699a4d7e86SSudarsana Reddy Kalluru 	channels->combined_count = QEDE_QUEUE_CNT(edev) - edev->fp_num_tx -
10709a4d7e86SSudarsana Reddy Kalluru 					edev->fp_num_rx;
10719a4d7e86SSudarsana Reddy Kalluru 	channels->tx_count = edev->fp_num_tx;
10729a4d7e86SSudarsana Reddy Kalluru 	channels->rx_count = edev->fp_num_rx;
10738edf049dSSudarsana Kalluru }
10748edf049dSSudarsana Kalluru 
10758edf049dSSudarsana Kalluru static int qede_set_channels(struct net_device *dev,
10768edf049dSSudarsana Kalluru 			     struct ethtool_channels *channels)
10778edf049dSSudarsana Kalluru {
10788edf049dSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
10799a4d7e86SSudarsana Reddy Kalluru 	u32 count;
10808edf049dSSudarsana Kalluru 
10818edf049dSSudarsana Kalluru 	DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
10828edf049dSSudarsana Kalluru 		   "set-channels command parameters: rx = %d, tx = %d, other = %d, combined = %d\n",
10838edf049dSSudarsana Kalluru 		   channels->rx_count, channels->tx_count,
10848edf049dSSudarsana Kalluru 		   channels->other_count, channels->combined_count);
10858edf049dSSudarsana Kalluru 
10869a4d7e86SSudarsana Reddy Kalluru 	count = channels->rx_count + channels->tx_count +
10879a4d7e86SSudarsana Reddy Kalluru 			channels->combined_count;
10889a4d7e86SSudarsana Reddy Kalluru 
10899a4d7e86SSudarsana Reddy Kalluru 	/* We don't support `other' channels */
10909a4d7e86SSudarsana Reddy Kalluru 	if (channels->other_count) {
10918edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
10928edf049dSSudarsana Kalluru 			   "command parameters not supported\n");
10938edf049dSSudarsana Kalluru 		return -EINVAL;
10948edf049dSSudarsana Kalluru 	}
10958edf049dSSudarsana Kalluru 
10969a4d7e86SSudarsana Reddy Kalluru 	if (!(channels->combined_count || (channels->rx_count &&
10979a4d7e86SSudarsana Reddy Kalluru 					   channels->tx_count))) {
10989a4d7e86SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
10999a4d7e86SSudarsana Reddy Kalluru 			   "need to request at least one transmit and one receive channel\n");
11009a4d7e86SSudarsana Reddy Kalluru 		return -EINVAL;
11019a4d7e86SSudarsana Reddy Kalluru 	}
11029a4d7e86SSudarsana Reddy Kalluru 
11039a4d7e86SSudarsana Reddy Kalluru 	if (count > QEDE_MAX_RSS_CNT(edev)) {
11049a4d7e86SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11059a4d7e86SSudarsana Reddy Kalluru 			   "requested channels = %d max supported channels = %d\n",
11069a4d7e86SSudarsana Reddy Kalluru 			   count, QEDE_MAX_RSS_CNT(edev));
11079a4d7e86SSudarsana Reddy Kalluru 		return -EINVAL;
11089a4d7e86SSudarsana Reddy Kalluru 	}
11099a4d7e86SSudarsana Reddy Kalluru 
11108edf049dSSudarsana Kalluru 	/* Check if there was a change in the active parameters */
11119a4d7e86SSudarsana Reddy Kalluru 	if ((count == QEDE_QUEUE_CNT(edev)) &&
11129a4d7e86SSudarsana Reddy Kalluru 	    (channels->tx_count == edev->fp_num_tx) &&
11139a4d7e86SSudarsana Reddy Kalluru 	    (channels->rx_count == edev->fp_num_rx)) {
11148edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11158edf049dSSudarsana Kalluru 			   "No change in active parameters\n");
11168edf049dSSudarsana Kalluru 		return 0;
11178edf049dSSudarsana Kalluru 	}
11188edf049dSSudarsana Kalluru 
11198edf049dSSudarsana Kalluru 	/* We need the number of queues to be divisible between the hwfns */
11209a4d7e86SSudarsana Reddy Kalluru 	if ((count % edev->dev_info.common.num_hwfns) ||
11219a4d7e86SSudarsana Reddy Kalluru 	    (channels->tx_count % edev->dev_info.common.num_hwfns) ||
11229a4d7e86SSudarsana Reddy Kalluru 	    (channels->rx_count % edev->dev_info.common.num_hwfns)) {
11238edf049dSSudarsana Kalluru 		DP_VERBOSE(edev, (NETIF_MSG_IFUP | NETIF_MSG_IFDOWN),
11249a4d7e86SSudarsana Reddy Kalluru 			   "Number of channels must be divisible by %04x\n",
11258edf049dSSudarsana Kalluru 			   edev->dev_info.common.num_hwfns);
11268edf049dSSudarsana Kalluru 		return -EINVAL;
11278edf049dSSudarsana Kalluru 	}
11288edf049dSSudarsana Kalluru 
11298edf049dSSudarsana Kalluru 	/* Set number of queues and reload if necessary */
11309a4d7e86SSudarsana Reddy Kalluru 	edev->req_queues = count;
11319a4d7e86SSudarsana Reddy Kalluru 	edev->req_num_tx = channels->tx_count;
11329a4d7e86SSudarsana Reddy Kalluru 	edev->req_num_rx = channels->rx_count;
1133ed0dd915SSudarsana Reddy Kalluru 	/* Reset the indirection table if rx queue count is updated */
1134ed0dd915SSudarsana Reddy Kalluru 	if ((edev->req_queues - edev->req_num_tx) != QEDE_RSS_COUNT(edev)) {
1135ed0dd915SSudarsana Reddy Kalluru 		edev->rss_params_inited &= ~QEDE_RSS_INDIR_INITED;
1136f29ffdb6SMintz, Yuval 		memset(edev->rss_ind_table, 0, sizeof(edev->rss_ind_table));
1137ed0dd915SSudarsana Reddy Kalluru 	}
1138ed0dd915SSudarsana Reddy Kalluru 
1139567b3c12SMintz, Yuval 	qede_reload(edev, NULL, false);
11408edf049dSSudarsana Kalluru 
11418edf049dSSudarsana Kalluru 	return 0;
11428edf049dSSudarsana Kalluru }
11438edf049dSSudarsana Kalluru 
11444c55215cSSudarsana Reddy Kalluru static int qede_get_ts_info(struct net_device *dev,
11454c55215cSSudarsana Reddy Kalluru 			    struct ethtool_ts_info *info)
11464c55215cSSudarsana Reddy Kalluru {
11474c55215cSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
11484c55215cSSudarsana Reddy Kalluru 
11494c55215cSSudarsana Reddy Kalluru 	return qede_ptp_get_ts_info(edev, info);
11504c55215cSSudarsana Reddy Kalluru }
11514c55215cSSudarsana Reddy Kalluru 
11523d971cbdSSudarsana Kalluru static int qede_set_phys_id(struct net_device *dev,
11533d971cbdSSudarsana Kalluru 			    enum ethtool_phys_id_state state)
11543d971cbdSSudarsana Kalluru {
11553d971cbdSSudarsana Kalluru 	struct qede_dev *edev = netdev_priv(dev);
11563d971cbdSSudarsana Kalluru 	u8 led_state = 0;
11573d971cbdSSudarsana Kalluru 
11583d971cbdSSudarsana Kalluru 	switch (state) {
11593d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ACTIVE:
11603d971cbdSSudarsana Kalluru 		return 1;	/* cycle on/off once per second */
11613d971cbdSSudarsana Kalluru 
11623d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_ON:
11633d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_ON;
11643d971cbdSSudarsana Kalluru 		break;
11653d971cbdSSudarsana Kalluru 
11663d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_OFF:
11673d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_OFF;
11683d971cbdSSudarsana Kalluru 		break;
11693d971cbdSSudarsana Kalluru 
11703d971cbdSSudarsana Kalluru 	case ETHTOOL_ID_INACTIVE:
11713d971cbdSSudarsana Kalluru 		led_state = QED_LED_MODE_RESTORE;
11723d971cbdSSudarsana Kalluru 		break;
11733d971cbdSSudarsana Kalluru 	}
11743d971cbdSSudarsana Kalluru 
11753d971cbdSSudarsana Kalluru 	edev->ops->common->set_led(edev->cdev, led_state);
11763d971cbdSSudarsana Kalluru 
11773d971cbdSSudarsana Kalluru 	return 0;
11783d971cbdSSudarsana Kalluru }
11793d971cbdSSudarsana Kalluru 
1180961acdeaSSudarsana Reddy Kalluru static int qede_get_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
1181961acdeaSSudarsana Reddy Kalluru {
1182961acdeaSSudarsana Reddy Kalluru 	info->data = RXH_IP_SRC | RXH_IP_DST;
1183961acdeaSSudarsana Reddy Kalluru 
1184961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
1185961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
1186961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
1187961acdeaSSudarsana Reddy Kalluru 		info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1188961acdeaSSudarsana Reddy Kalluru 		break;
1189961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
1190f29ffdb6SMintz, Yuval 		if (edev->rss_caps & QED_RSS_IPV4_UDP)
1191961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1192961acdeaSSudarsana Reddy Kalluru 		break;
1193961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
1194f29ffdb6SMintz, Yuval 		if (edev->rss_caps & QED_RSS_IPV6_UDP)
1195961acdeaSSudarsana Reddy Kalluru 			info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
1196961acdeaSSudarsana Reddy Kalluru 		break;
1197961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
1198961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
1199961acdeaSSudarsana Reddy Kalluru 		break;
1200961acdeaSSudarsana Reddy Kalluru 	default:
1201961acdeaSSudarsana Reddy Kalluru 		info->data = 0;
1202961acdeaSSudarsana Reddy Kalluru 		break;
1203961acdeaSSudarsana Reddy Kalluru 	}
1204961acdeaSSudarsana Reddy Kalluru 
1205961acdeaSSudarsana Reddy Kalluru 	return 0;
1206961acdeaSSudarsana Reddy Kalluru }
1207961acdeaSSudarsana Reddy Kalluru 
1208961acdeaSSudarsana Reddy Kalluru static int qede_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
1209ec9b8dbdSChopra, Manish 			  u32 *rule_locs)
1210961acdeaSSudarsana Reddy Kalluru {
1211961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1212ec9b8dbdSChopra, Manish 	int rc = 0;
1213961acdeaSSudarsana Reddy Kalluru 
1214961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
1215961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXRINGS:
12169a4d7e86SSudarsana Reddy Kalluru 		info->data = QEDE_RSS_COUNT(edev);
1217ec9b8dbdSChopra, Manish 		break;
1218961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_GRXFH:
1219ec9b8dbdSChopra, Manish 		rc = qede_get_rss_flags(edev, info);
1220ec9b8dbdSChopra, Manish 		break;
1221ec9b8dbdSChopra, Manish 	case ETHTOOL_GRXCLSRLCNT:
1222ec9b8dbdSChopra, Manish 		info->rule_cnt = qede_get_arfs_filter_count(edev);
1223ec9b8dbdSChopra, Manish 		info->data = QEDE_RFS_MAX_FLTR;
1224ec9b8dbdSChopra, Manish 		break;
1225ec9b8dbdSChopra, Manish 	case ETHTOOL_GRXCLSRULE:
1226ec9b8dbdSChopra, Manish 		rc = qede_get_cls_rule_entry(edev, info);
1227ec9b8dbdSChopra, Manish 		break;
1228ec9b8dbdSChopra, Manish 	case ETHTOOL_GRXCLSRLALL:
1229ec9b8dbdSChopra, Manish 		rc = qede_get_cls_rule_all(edev, info, rule_locs);
1230ec9b8dbdSChopra, Manish 		break;
1231961acdeaSSudarsana Reddy Kalluru 	default:
1232961acdeaSSudarsana Reddy Kalluru 		DP_ERR(edev, "Command parameters not supported\n");
1233ec9b8dbdSChopra, Manish 		rc = -EOPNOTSUPP;
1234961acdeaSSudarsana Reddy Kalluru 	}
1235ec9b8dbdSChopra, Manish 
1236ec9b8dbdSChopra, Manish 	return rc;
1237961acdeaSSudarsana Reddy Kalluru }
1238961acdeaSSudarsana Reddy Kalluru 
1239961acdeaSSudarsana Reddy Kalluru static int qede_set_rss_flags(struct qede_dev *edev, struct ethtool_rxnfc *info)
1240961acdeaSSudarsana Reddy Kalluru {
1241f29ffdb6SMintz, Yuval 	struct qed_update_vport_params *vport_update_params;
1242961acdeaSSudarsana Reddy Kalluru 	u8 set_caps = 0, clr_caps = 0;
1243f29ffdb6SMintz, Yuval 	int rc = 0;
1244961acdeaSSudarsana Reddy Kalluru 
1245961acdeaSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
1246961acdeaSSudarsana Reddy Kalluru 		   "Set rss flags command parameters: flow type = %d, data = %llu\n",
1247961acdeaSSudarsana Reddy Kalluru 		   info->flow_type, info->data);
1248961acdeaSSudarsana Reddy Kalluru 
1249961acdeaSSudarsana Reddy Kalluru 	switch (info->flow_type) {
1250961acdeaSSudarsana Reddy Kalluru 	case TCP_V4_FLOW:
1251961acdeaSSudarsana Reddy Kalluru 	case TCP_V6_FLOW:
1252961acdeaSSudarsana Reddy Kalluru 		/* For TCP only 4-tuple hash is supported */
1253961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST |
1254961acdeaSSudarsana Reddy Kalluru 				  RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1255961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
1256961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1257961acdeaSSudarsana Reddy Kalluru 		}
1258961acdeaSSudarsana Reddy Kalluru 		return 0;
1259961acdeaSSudarsana Reddy Kalluru 	case UDP_V4_FLOW:
1260961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
1261961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
1262961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1263961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV4_UDP;
1264961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1265961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
1266961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
1267961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV4_UDP;
1268961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1269961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
1270961acdeaSSudarsana Reddy Kalluru 		} else {
1271961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1272961acdeaSSudarsana Reddy Kalluru 		}
1273961acdeaSSudarsana Reddy Kalluru 		break;
1274961acdeaSSudarsana Reddy Kalluru 	case UDP_V6_FLOW:
1275961acdeaSSudarsana Reddy Kalluru 		/* For UDP either 2-tuple hash or 4-tuple hash is supported */
1276961acdeaSSudarsana Reddy Kalluru 		if (info->data == (RXH_IP_SRC | RXH_IP_DST |
1277961acdeaSSudarsana Reddy Kalluru 				   RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
1278961acdeaSSudarsana Reddy Kalluru 			set_caps = QED_RSS_IPV6_UDP;
1279961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1280961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple enabled\n");
1281961acdeaSSudarsana Reddy Kalluru 		} else if (info->data == (RXH_IP_SRC | RXH_IP_DST)) {
1282961acdeaSSudarsana Reddy Kalluru 			clr_caps = QED_RSS_IPV6_UDP;
1283961acdeaSSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
1284961acdeaSSudarsana Reddy Kalluru 				   "UDP 4-tuple disabled\n");
1285961acdeaSSudarsana Reddy Kalluru 		} else {
1286961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1287961acdeaSSudarsana Reddy Kalluru 		}
1288961acdeaSSudarsana Reddy Kalluru 		break;
1289961acdeaSSudarsana Reddy Kalluru 	case IPV4_FLOW:
1290961acdeaSSudarsana Reddy Kalluru 	case IPV6_FLOW:
1291961acdeaSSudarsana Reddy Kalluru 		/* For IP only 2-tuple hash is supported */
1292961acdeaSSudarsana Reddy Kalluru 		if (info->data ^ (RXH_IP_SRC | RXH_IP_DST)) {
1293961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
1294961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1295961acdeaSSudarsana Reddy Kalluru 		}
1296961acdeaSSudarsana Reddy Kalluru 		return 0;
1297961acdeaSSudarsana Reddy Kalluru 	case SCTP_V4_FLOW:
1298961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V4_FLOW:
1299961acdeaSSudarsana Reddy Kalluru 	case AH_V4_FLOW:
1300961acdeaSSudarsana Reddy Kalluru 	case ESP_V4_FLOW:
1301961acdeaSSudarsana Reddy Kalluru 	case SCTP_V6_FLOW:
1302961acdeaSSudarsana Reddy Kalluru 	case AH_ESP_V6_FLOW:
1303961acdeaSSudarsana Reddy Kalluru 	case AH_V6_FLOW:
1304961acdeaSSudarsana Reddy Kalluru 	case ESP_V6_FLOW:
1305961acdeaSSudarsana Reddy Kalluru 	case IP_USER_FLOW:
1306961acdeaSSudarsana Reddy Kalluru 	case ETHER_FLOW:
1307961acdeaSSudarsana Reddy Kalluru 		/* RSS is not supported for these protocols */
1308961acdeaSSudarsana Reddy Kalluru 		if (info->data) {
1309961acdeaSSudarsana Reddy Kalluru 			DP_INFO(edev, "Command parameters not supported\n");
1310961acdeaSSudarsana Reddy Kalluru 			return -EINVAL;
1311961acdeaSSudarsana Reddy Kalluru 		}
1312961acdeaSSudarsana Reddy Kalluru 		return 0;
1313961acdeaSSudarsana Reddy Kalluru 	default:
1314961acdeaSSudarsana Reddy Kalluru 		return -EINVAL;
1315961acdeaSSudarsana Reddy Kalluru 	}
1316961acdeaSSudarsana Reddy Kalluru 
1317961acdeaSSudarsana Reddy Kalluru 	/* No action is needed if there is no change in the rss capability */
1318f29ffdb6SMintz, Yuval 	if (edev->rss_caps == ((edev->rss_caps & ~clr_caps) | set_caps))
1319961acdeaSSudarsana Reddy Kalluru 		return 0;
1320961acdeaSSudarsana Reddy Kalluru 
1321961acdeaSSudarsana Reddy Kalluru 	/* Update internal configuration */
1322f29ffdb6SMintz, Yuval 	edev->rss_caps = ((edev->rss_caps & ~clr_caps) | set_caps);
1323961acdeaSSudarsana Reddy Kalluru 	edev->rss_params_inited |= QEDE_RSS_CAPS_INITED;
1324961acdeaSSudarsana Reddy Kalluru 
1325961acdeaSSudarsana Reddy Kalluru 	/* Re-configure if possible */
1326f29ffdb6SMintz, Yuval 	__qede_lock(edev);
1327f29ffdb6SMintz, Yuval 	if (edev->state == QEDE_STATE_OPEN) {
1328f29ffdb6SMintz, Yuval 		vport_update_params = vzalloc(sizeof(*vport_update_params));
1329f29ffdb6SMintz, Yuval 		if (!vport_update_params) {
1330f29ffdb6SMintz, Yuval 			__qede_unlock(edev);
1331f29ffdb6SMintz, Yuval 			return -ENOMEM;
1332961acdeaSSudarsana Reddy Kalluru 		}
1333f29ffdb6SMintz, Yuval 		qede_fill_rss_params(edev, &vport_update_params->rss_params,
1334f29ffdb6SMintz, Yuval 				     &vport_update_params->update_rss_flg);
1335f29ffdb6SMintz, Yuval 		rc = edev->ops->vport_update(edev->cdev, vport_update_params);
1336f29ffdb6SMintz, Yuval 		vfree(vport_update_params);
1337f29ffdb6SMintz, Yuval 	}
1338f29ffdb6SMintz, Yuval 	__qede_unlock(edev);
1339961acdeaSSudarsana Reddy Kalluru 
1340f29ffdb6SMintz, Yuval 	return rc;
1341961acdeaSSudarsana Reddy Kalluru }
1342961acdeaSSudarsana Reddy Kalluru 
1343961acdeaSSudarsana Reddy Kalluru static int qede_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
1344961acdeaSSudarsana Reddy Kalluru {
1345961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
13463f2a2b8bSChopra, Manish 	int rc;
1347961acdeaSSudarsana Reddy Kalluru 
1348961acdeaSSudarsana Reddy Kalluru 	switch (info->cmd) {
1349961acdeaSSudarsana Reddy Kalluru 	case ETHTOOL_SRXFH:
13503f2a2b8bSChopra, Manish 		rc = qede_set_rss_flags(edev, info);
13513f2a2b8bSChopra, Manish 		break;
13523f2a2b8bSChopra, Manish 	case ETHTOOL_SRXCLSRLINS:
13533f2a2b8bSChopra, Manish 		rc = qede_add_cls_rule(edev, info);
13543f2a2b8bSChopra, Manish 		break;
13553f2a2b8bSChopra, Manish 	case ETHTOOL_SRXCLSRLDEL:
13562ce9c93eSManish Chopra 		rc = qede_delete_flow_filter(edev, info->fs.location);
13573f2a2b8bSChopra, Manish 		break;
1358961acdeaSSudarsana Reddy Kalluru 	default:
1359961acdeaSSudarsana Reddy Kalluru 		DP_INFO(edev, "Command parameters not supported\n");
13603f2a2b8bSChopra, Manish 		rc = -EOPNOTSUPP;
1361961acdeaSSudarsana Reddy Kalluru 	}
13623f2a2b8bSChopra, Manish 
13633f2a2b8bSChopra, Manish 	return rc;
1364961acdeaSSudarsana Reddy Kalluru }
1365961acdeaSSudarsana Reddy Kalluru 
1366961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_indir_size(struct net_device *dev)
1367961acdeaSSudarsana Reddy Kalluru {
1368961acdeaSSudarsana Reddy Kalluru 	return QED_RSS_IND_TABLE_SIZE;
1369961acdeaSSudarsana Reddy Kalluru }
1370961acdeaSSudarsana Reddy Kalluru 
1371961acdeaSSudarsana Reddy Kalluru static u32 qede_get_rxfh_key_size(struct net_device *dev)
1372961acdeaSSudarsana Reddy Kalluru {
1373961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1374961acdeaSSudarsana Reddy Kalluru 
1375f29ffdb6SMintz, Yuval 	return sizeof(edev->rss_key);
1376961acdeaSSudarsana Reddy Kalluru }
1377961acdeaSSudarsana Reddy Kalluru 
1378961acdeaSSudarsana Reddy Kalluru static int qede_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc)
1379961acdeaSSudarsana Reddy Kalluru {
1380961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1381961acdeaSSudarsana Reddy Kalluru 	int i;
1382961acdeaSSudarsana Reddy Kalluru 
1383961acdeaSSudarsana Reddy Kalluru 	if (hfunc)
1384961acdeaSSudarsana Reddy Kalluru 		*hfunc = ETH_RSS_HASH_TOP;
1385961acdeaSSudarsana Reddy Kalluru 
1386961acdeaSSudarsana Reddy Kalluru 	if (!indir)
1387961acdeaSSudarsana Reddy Kalluru 		return 0;
1388961acdeaSSudarsana Reddy Kalluru 
1389961acdeaSSudarsana Reddy Kalluru 	for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1390f29ffdb6SMintz, Yuval 		indir[i] = edev->rss_ind_table[i];
1391961acdeaSSudarsana Reddy Kalluru 
1392961acdeaSSudarsana Reddy Kalluru 	if (key)
1393f29ffdb6SMintz, Yuval 		memcpy(key, edev->rss_key, qede_get_rxfh_key_size(dev));
1394961acdeaSSudarsana Reddy Kalluru 
1395961acdeaSSudarsana Reddy Kalluru 	return 0;
1396961acdeaSSudarsana Reddy Kalluru }
1397961acdeaSSudarsana Reddy Kalluru 
1398961acdeaSSudarsana Reddy Kalluru static int qede_set_rxfh(struct net_device *dev, const u32 *indir,
1399961acdeaSSudarsana Reddy Kalluru 			 const u8 *key, const u8 hfunc)
1400961acdeaSSudarsana Reddy Kalluru {
1401f29ffdb6SMintz, Yuval 	struct qed_update_vport_params *vport_update_params;
1402961acdeaSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1403f29ffdb6SMintz, Yuval 	int i, rc = 0;
1404961acdeaSSudarsana Reddy Kalluru 
1405ba300ce3SSudarsana Reddy Kalluru 	if (edev->dev_info.common.num_hwfns > 1) {
1406ba300ce3SSudarsana Reddy Kalluru 		DP_INFO(edev,
1407ba300ce3SSudarsana Reddy Kalluru 			"RSS configuration is not supported for 100G devices\n");
1408ba300ce3SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1409ba300ce3SSudarsana Reddy Kalluru 	}
1410ba300ce3SSudarsana Reddy Kalluru 
1411961acdeaSSudarsana Reddy Kalluru 	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
1412961acdeaSSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1413961acdeaSSudarsana Reddy Kalluru 
1414961acdeaSSudarsana Reddy Kalluru 	if (!indir && !key)
1415961acdeaSSudarsana Reddy Kalluru 		return 0;
1416961acdeaSSudarsana Reddy Kalluru 
1417961acdeaSSudarsana Reddy Kalluru 	if (indir) {
1418961acdeaSSudarsana Reddy Kalluru 		for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++)
1419f29ffdb6SMintz, Yuval 			edev->rss_ind_table[i] = indir[i];
1420961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_INDIR_INITED;
1421961acdeaSSudarsana Reddy Kalluru 	}
1422961acdeaSSudarsana Reddy Kalluru 
1423961acdeaSSudarsana Reddy Kalluru 	if (key) {
1424f29ffdb6SMintz, Yuval 		memcpy(&edev->rss_key, key, qede_get_rxfh_key_size(dev));
1425961acdeaSSudarsana Reddy Kalluru 		edev->rss_params_inited |= QEDE_RSS_KEY_INITED;
1426961acdeaSSudarsana Reddy Kalluru 	}
1427961acdeaSSudarsana Reddy Kalluru 
1428f29ffdb6SMintz, Yuval 	__qede_lock(edev);
1429f29ffdb6SMintz, Yuval 	if (edev->state == QEDE_STATE_OPEN) {
1430f29ffdb6SMintz, Yuval 		vport_update_params = vzalloc(sizeof(*vport_update_params));
1431f29ffdb6SMintz, Yuval 		if (!vport_update_params) {
1432f29ffdb6SMintz, Yuval 			__qede_unlock(edev);
1433f29ffdb6SMintz, Yuval 			return -ENOMEM;
1434961acdeaSSudarsana Reddy Kalluru 		}
1435f29ffdb6SMintz, Yuval 		qede_fill_rss_params(edev, &vport_update_params->rss_params,
1436f29ffdb6SMintz, Yuval 				     &vport_update_params->update_rss_flg);
1437f29ffdb6SMintz, Yuval 		rc = edev->ops->vport_update(edev->cdev, vport_update_params);
1438f29ffdb6SMintz, Yuval 		vfree(vport_update_params);
1439f29ffdb6SMintz, Yuval 	}
1440f29ffdb6SMintz, Yuval 	__qede_unlock(edev);
1441961acdeaSSudarsana Reddy Kalluru 
1442f29ffdb6SMintz, Yuval 	return rc;
1443961acdeaSSudarsana Reddy Kalluru }
1444961acdeaSSudarsana Reddy Kalluru 
144516f46bf0SSudarsana Reddy Kalluru /* This function enables the interrupt generation and the NAPI on the device */
144616f46bf0SSudarsana Reddy Kalluru static void qede_netif_start(struct qede_dev *edev)
144716f46bf0SSudarsana Reddy Kalluru {
144816f46bf0SSudarsana Reddy Kalluru 	int i;
144916f46bf0SSudarsana Reddy Kalluru 
145016f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev))
145116f46bf0SSudarsana Reddy Kalluru 		return;
145216f46bf0SSudarsana Reddy Kalluru 
14539a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
145416f46bf0SSudarsana Reddy Kalluru 		/* Update and reenable interrupts */
145516f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_ENABLE, 1);
145616f46bf0SSudarsana Reddy Kalluru 		napi_enable(&edev->fp_array[i].napi);
145716f46bf0SSudarsana Reddy Kalluru 	}
145816f46bf0SSudarsana Reddy Kalluru }
145916f46bf0SSudarsana Reddy Kalluru 
146016f46bf0SSudarsana Reddy Kalluru /* This function disables the NAPI and the interrupt generation on the device */
146116f46bf0SSudarsana Reddy Kalluru static void qede_netif_stop(struct qede_dev *edev)
146216f46bf0SSudarsana Reddy Kalluru {
146316f46bf0SSudarsana Reddy Kalluru 	int i;
146416f46bf0SSudarsana Reddy Kalluru 
14659a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
146616f46bf0SSudarsana Reddy Kalluru 		napi_disable(&edev->fp_array[i].napi);
146716f46bf0SSudarsana Reddy Kalluru 		/* Disable interrupts */
146816f46bf0SSudarsana Reddy Kalluru 		qed_sb_ack(edev->fp_array[i].sb_info, IGU_INT_DISABLE, 0);
146916f46bf0SSudarsana Reddy Kalluru 	}
147016f46bf0SSudarsana Reddy Kalluru }
147116f46bf0SSudarsana Reddy Kalluru 
147216f46bf0SSudarsana Reddy Kalluru static int qede_selftest_transmit_traffic(struct qede_dev *edev,
147316f46bf0SSudarsana Reddy Kalluru 					  struct sk_buff *skb)
147416f46bf0SSudarsana Reddy Kalluru {
14759a4d7e86SSudarsana Reddy Kalluru 	struct qede_tx_queue *txq = NULL;
147616f46bf0SSudarsana Reddy Kalluru 	struct eth_tx_1st_bd *first_bd;
147716f46bf0SSudarsana Reddy Kalluru 	dma_addr_t mapping;
147848848a06SManish Chopra 	int i, idx;
147948848a06SManish Chopra 	u16 val;
148016f46bf0SSudarsana Reddy Kalluru 
14819a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
14825e7baf0fSManish Chopra 		struct qede_fastpath *fp = &edev->fp_array[i];
14835e7baf0fSManish Chopra 
14845e7baf0fSManish Chopra 		if (fp->type & QEDE_FASTPATH_TX) {
14855e7baf0fSManish Chopra 			txq = QEDE_FP_TC0_TXQ(fp);
14869a4d7e86SSudarsana Reddy Kalluru 			break;
14879a4d7e86SSudarsana Reddy Kalluru 		}
14889a4d7e86SSudarsana Reddy Kalluru 	}
14899a4d7e86SSudarsana Reddy Kalluru 
14909a4d7e86SSudarsana Reddy Kalluru 	if (!txq) {
14919a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx path is not available\n");
14929a4d7e86SSudarsana Reddy Kalluru 		return -1;
14939a4d7e86SSudarsana Reddy Kalluru 	}
14949a4d7e86SSudarsana Reddy Kalluru 
149516f46bf0SSudarsana Reddy Kalluru 	/* Fill the entry in the SW ring and the BDs in the FW ring */
14965a052d62SSudarsana Reddy Kalluru 	idx = txq->sw_tx_prod;
1497cb6aeb07SMintz, Yuval 	txq->sw_tx_ring.skbs[idx].skb = skb;
149816f46bf0SSudarsana Reddy Kalluru 	first_bd = qed_chain_produce(&txq->tx_pbl);
149916f46bf0SSudarsana Reddy Kalluru 	memset(first_bd, 0, sizeof(*first_bd));
150016f46bf0SSudarsana Reddy Kalluru 	val = 1 << ETH_TX_1ST_BD_FLAGS_START_BD_SHIFT;
150116f46bf0SSudarsana Reddy Kalluru 	first_bd->data.bd_flags.bitfields = val;
1502351a4dedSYuval Mintz 	val = skb->len & ETH_TX_DATA_1ST_BD_PKT_LEN_MASK;
150348848a06SManish Chopra 	val = val << ETH_TX_DATA_1ST_BD_PKT_LEN_SHIFT;
150448848a06SManish Chopra 	first_bd->data.bitfields |= cpu_to_le16(val);
150516f46bf0SSudarsana Reddy Kalluru 
150616f46bf0SSudarsana Reddy Kalluru 	/* Map skb linear data for DMA and set in the first BD */
150716f46bf0SSudarsana Reddy Kalluru 	mapping = dma_map_single(&edev->pdev->dev, skb->data,
150816f46bf0SSudarsana Reddy Kalluru 				 skb_headlen(skb), DMA_TO_DEVICE);
150916f46bf0SSudarsana Reddy Kalluru 	if (unlikely(dma_mapping_error(&edev->pdev->dev, mapping))) {
151016f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "SKB mapping failed\n");
151116f46bf0SSudarsana Reddy Kalluru 		return -ENOMEM;
151216f46bf0SSudarsana Reddy Kalluru 	}
151316f46bf0SSudarsana Reddy Kalluru 	BD_SET_UNMAP_ADDR_LEN(first_bd, mapping, skb_headlen(skb));
151416f46bf0SSudarsana Reddy Kalluru 
151516f46bf0SSudarsana Reddy Kalluru 	/* update the first BD with the actual num BDs */
151616f46bf0SSudarsana Reddy Kalluru 	first_bd->data.nbds = 1;
15175a052d62SSudarsana Reddy Kalluru 	txq->sw_tx_prod = (txq->sw_tx_prod + 1) % txq->num_tx_buffers;
151816f46bf0SSudarsana Reddy Kalluru 	/* 'next page' entries are counted in the producer value */
151948848a06SManish Chopra 	val = qed_chain_get_prod_idx(&txq->tx_pbl);
152048848a06SManish Chopra 	txq->tx_db.data.bd_prod = cpu_to_le16(val);
152116f46bf0SSudarsana Reddy Kalluru 
152216f46bf0SSudarsana Reddy Kalluru 	/* wmb makes sure that the BDs data is updated before updating the
152316f46bf0SSudarsana Reddy Kalluru 	 * producer, otherwise FW may read old data from the BDs.
152416f46bf0SSudarsana Reddy Kalluru 	 */
152516f46bf0SSudarsana Reddy Kalluru 	wmb();
152616f46bf0SSudarsana Reddy Kalluru 	barrier();
152716f46bf0SSudarsana Reddy Kalluru 	writel(txq->tx_db.raw, txq->doorbell_addr);
152816f46bf0SSudarsana Reddy Kalluru 
152916f46bf0SSudarsana Reddy Kalluru 	/* mmiowb is needed to synchronize doorbell writes from more than one
153016f46bf0SSudarsana Reddy Kalluru 	 * processor. It guarantees that the write arrives to the device before
153116f46bf0SSudarsana Reddy Kalluru 	 * the queue lock is released and another start_xmit is called (possibly
153216f46bf0SSudarsana Reddy Kalluru 	 * on another CPU). Without this barrier, the next doorbell can bypass
153316f46bf0SSudarsana Reddy Kalluru 	 * this doorbell. This is applicable to IA64/Altix systems.
153416f46bf0SSudarsana Reddy Kalluru 	 */
153516f46bf0SSudarsana Reddy Kalluru 	mmiowb();
153616f46bf0SSudarsana Reddy Kalluru 
153716f46bf0SSudarsana Reddy Kalluru 	for (i = 0; i < QEDE_SELFTEST_POLL_COUNT; i++) {
153816f46bf0SSudarsana Reddy Kalluru 		if (qede_txq_has_work(txq))
153916f46bf0SSudarsana Reddy Kalluru 			break;
154016f46bf0SSudarsana Reddy Kalluru 		usleep_range(100, 200);
154116f46bf0SSudarsana Reddy Kalluru 	}
154216f46bf0SSudarsana Reddy Kalluru 
154316f46bf0SSudarsana Reddy Kalluru 	if (!qede_txq_has_work(txq)) {
154416f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Tx completion didn't happen\n");
154516f46bf0SSudarsana Reddy Kalluru 		return -1;
154616f46bf0SSudarsana Reddy Kalluru 	}
154716f46bf0SSudarsana Reddy Kalluru 
154816f46bf0SSudarsana Reddy Kalluru 	first_bd = (struct eth_tx_1st_bd *)qed_chain_consume(&txq->tx_pbl);
1549fabd545cSManish Chopra 	dma_unmap_single(&edev->pdev->dev, BD_UNMAP_ADDR(first_bd),
155016f46bf0SSudarsana Reddy Kalluru 			 BD_UNMAP_LEN(first_bd), DMA_TO_DEVICE);
15515a052d62SSudarsana Reddy Kalluru 	txq->sw_tx_cons = (txq->sw_tx_cons + 1) % txq->num_tx_buffers;
1552cb6aeb07SMintz, Yuval 	txq->sw_tx_ring.skbs[idx].skb = NULL;
155316f46bf0SSudarsana Reddy Kalluru 
155416f46bf0SSudarsana Reddy Kalluru 	return 0;
155516f46bf0SSudarsana Reddy Kalluru }
155616f46bf0SSudarsana Reddy Kalluru 
155716f46bf0SSudarsana Reddy Kalluru static int qede_selftest_receive_traffic(struct qede_dev *edev)
155816f46bf0SSudarsana Reddy Kalluru {
155916f46bf0SSudarsana Reddy Kalluru 	u16 hw_comp_cons, sw_comp_cons, sw_rx_index, len;
156016f46bf0SSudarsana Reddy Kalluru 	struct eth_fast_path_rx_reg_cqe *fp_cqe;
15619a4d7e86SSudarsana Reddy Kalluru 	struct qede_rx_queue *rxq = NULL;
156216f46bf0SSudarsana Reddy Kalluru 	struct sw_rx_data *sw_rx_data;
156316f46bf0SSudarsana Reddy Kalluru 	union eth_rx_cqe *cqe;
1564afe981d6SSudarsana Reddy Kalluru 	int i, iter, rc = 0;
156516f46bf0SSudarsana Reddy Kalluru 	u8 *data_ptr;
156616f46bf0SSudarsana Reddy Kalluru 
15679a4d7e86SSudarsana Reddy Kalluru 	for_each_queue(i) {
15689a4d7e86SSudarsana Reddy Kalluru 		if (edev->fp_array[i].type & QEDE_FASTPATH_RX) {
15699a4d7e86SSudarsana Reddy Kalluru 			rxq = edev->fp_array[i].rxq;
15709a4d7e86SSudarsana Reddy Kalluru 			break;
15719a4d7e86SSudarsana Reddy Kalluru 		}
15729a4d7e86SSudarsana Reddy Kalluru 	}
15739a4d7e86SSudarsana Reddy Kalluru 
15749a4d7e86SSudarsana Reddy Kalluru 	if (!rxq) {
15759a4d7e86SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Rx path is not available\n");
15769a4d7e86SSudarsana Reddy Kalluru 		return -1;
15779a4d7e86SSudarsana Reddy Kalluru 	}
15789a4d7e86SSudarsana Reddy Kalluru 
157916f46bf0SSudarsana Reddy Kalluru 	/* The packet is expected to receive on rx-queue 0 even though RSS is
158016f46bf0SSudarsana Reddy Kalluru 	 * enabled. This is because the queue 0 is configured as the default
158116f46bf0SSudarsana Reddy Kalluru 	 * queue and that the loopback traffic is not IP.
158216f46bf0SSudarsana Reddy Kalluru 	 */
1583afe981d6SSudarsana Reddy Kalluru 	for (iter = 0; iter < QEDE_SELFTEST_POLL_COUNT; iter++) {
158416f46bf0SSudarsana Reddy Kalluru 		if (!qede_has_rx_work(rxq)) {
1585837d4eb6SSudarsana Reddy Kalluru 			usleep_range(100, 200);
1586837d4eb6SSudarsana Reddy Kalluru 			continue;
158716f46bf0SSudarsana Reddy Kalluru 		}
158816f46bf0SSudarsana Reddy Kalluru 
158916f46bf0SSudarsana Reddy Kalluru 		hw_comp_cons = le16_to_cpu(*rxq->hw_cons_ptr);
159016f46bf0SSudarsana Reddy Kalluru 		sw_comp_cons = qed_chain_get_cons_idx(&rxq->rx_comp_ring);
159116f46bf0SSudarsana Reddy Kalluru 
1592837d4eb6SSudarsana Reddy Kalluru 		/* Memory barrier to prevent the CPU from doing speculative
1593837d4eb6SSudarsana Reddy Kalluru 		 * reads of CQE/BD before reading hw_comp_cons. If the CQE is
1594837d4eb6SSudarsana Reddy Kalluru 		 * read before it is written by FW, then FW writes CQE and SB,
1595837d4eb6SSudarsana Reddy Kalluru 		 * and then the CPU reads the hw_comp_cons, it will use an old
1596837d4eb6SSudarsana Reddy Kalluru 		 * CQE.
159716f46bf0SSudarsana Reddy Kalluru 		 */
159816f46bf0SSudarsana Reddy Kalluru 		rmb();
159916f46bf0SSudarsana Reddy Kalluru 
160016f46bf0SSudarsana Reddy Kalluru 		/* Get the CQE from the completion ring */
160116f46bf0SSudarsana Reddy Kalluru 		cqe = (union eth_rx_cqe *)qed_chain_consume(&rxq->rx_comp_ring);
160216f46bf0SSudarsana Reddy Kalluru 
160316f46bf0SSudarsana Reddy Kalluru 		/* Get the data from the SW ring */
160416f46bf0SSudarsana Reddy Kalluru 		sw_rx_index = rxq->sw_rx_cons & NUM_RX_BDS_MAX;
160516f46bf0SSudarsana Reddy Kalluru 		sw_rx_data = &rxq->sw_rx_ring[sw_rx_index];
160616f46bf0SSudarsana Reddy Kalluru 		fp_cqe = &cqe->fast_path_regular;
160716f46bf0SSudarsana Reddy Kalluru 		len =  le16_to_cpu(fp_cqe->len_on_first_bd);
160816f46bf0SSudarsana Reddy Kalluru 		data_ptr = (u8 *)(page_address(sw_rx_data->data) +
1609837d4eb6SSudarsana Reddy Kalluru 				  fp_cqe->placement_offset +
16108a863397SManish Chopra 				  sw_rx_data->page_offset +
16118a863397SManish Chopra 				  rxq->rx_headroom);
1612837d4eb6SSudarsana Reddy Kalluru 		if (ether_addr_equal(data_ptr,  edev->ndev->dev_addr) &&
1613837d4eb6SSudarsana Reddy Kalluru 		    ether_addr_equal(data_ptr + ETH_ALEN,
1614837d4eb6SSudarsana Reddy Kalluru 				     edev->ndev->dev_addr)) {
161516f46bf0SSudarsana Reddy Kalluru 			for (i = ETH_HLEN; i < len; i++)
161616f46bf0SSudarsana Reddy Kalluru 				if (data_ptr[i] != (unsigned char)(i & 0xff)) {
1617837d4eb6SSudarsana Reddy Kalluru 					rc = -1;
1618837d4eb6SSudarsana Reddy Kalluru 					break;
161916f46bf0SSudarsana Reddy Kalluru 				}
162016f46bf0SSudarsana Reddy Kalluru 
16219eb22357SMintz, Yuval 			qede_recycle_rx_bd_ring(rxq, 1);
1622837d4eb6SSudarsana Reddy Kalluru 			qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1623837d4eb6SSudarsana Reddy Kalluru 			break;
1624837d4eb6SSudarsana Reddy Kalluru 		}
162516f46bf0SSudarsana Reddy Kalluru 
1626837d4eb6SSudarsana Reddy Kalluru 		DP_INFO(edev, "Not the transmitted packet\n");
16279eb22357SMintz, Yuval 		qede_recycle_rx_bd_ring(rxq, 1);
1628837d4eb6SSudarsana Reddy Kalluru 		qed_chain_recycle_consumed(&rxq->rx_comp_ring);
1629837d4eb6SSudarsana Reddy Kalluru 	}
1630837d4eb6SSudarsana Reddy Kalluru 
1631afe981d6SSudarsana Reddy Kalluru 	if (iter == QEDE_SELFTEST_POLL_COUNT) {
1632837d4eb6SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Failed to receive the traffic\n");
1633837d4eb6SSudarsana Reddy Kalluru 		return -1;
1634837d4eb6SSudarsana Reddy Kalluru 	}
1635837d4eb6SSudarsana Reddy Kalluru 
1636837d4eb6SSudarsana Reddy Kalluru 	qede_update_rx_prod(edev, rxq);
1637837d4eb6SSudarsana Reddy Kalluru 
1638837d4eb6SSudarsana Reddy Kalluru 	return rc;
163916f46bf0SSudarsana Reddy Kalluru }
164016f46bf0SSudarsana Reddy Kalluru 
164116f46bf0SSudarsana Reddy Kalluru static int qede_selftest_run_loopback(struct qede_dev *edev, u32 loopback_mode)
164216f46bf0SSudarsana Reddy Kalluru {
164316f46bf0SSudarsana Reddy Kalluru 	struct qed_link_params link_params;
164416f46bf0SSudarsana Reddy Kalluru 	struct sk_buff *skb = NULL;
164516f46bf0SSudarsana Reddy Kalluru 	int rc = 0, i;
164616f46bf0SSudarsana Reddy Kalluru 	u32 pkt_size;
164716f46bf0SSudarsana Reddy Kalluru 	u8 *packet;
164816f46bf0SSudarsana Reddy Kalluru 
164916f46bf0SSudarsana Reddy Kalluru 	if (!netif_running(edev->ndev)) {
165016f46bf0SSudarsana Reddy Kalluru 		DP_NOTICE(edev, "Interface is down\n");
165116f46bf0SSudarsana Reddy Kalluru 		return -EINVAL;
165216f46bf0SSudarsana Reddy Kalluru 	}
165316f46bf0SSudarsana Reddy Kalluru 
165416f46bf0SSudarsana Reddy Kalluru 	qede_netif_stop(edev);
165516f46bf0SSudarsana Reddy Kalluru 
165616f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Loopback mode */
165716f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
165816f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
165916f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
166016f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = loopback_mode;
166116f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
166216f46bf0SSudarsana Reddy Kalluru 
166316f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
166416f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
166516f46bf0SSudarsana Reddy Kalluru 
1666b89869daSSudarsana Reddy Kalluru 	/* Setting max packet size to 1.5K to avoid data being split over
1667b89869daSSudarsana Reddy Kalluru 	 * multiple BDs in cases where MTU > PAGE_SIZE.
1668b89869daSSudarsana Reddy Kalluru 	 */
1669b89869daSSudarsana Reddy Kalluru 	pkt_size = (((edev->ndev->mtu < ETH_DATA_LEN) ?
1670b89869daSSudarsana Reddy Kalluru 		     edev->ndev->mtu : ETH_DATA_LEN) + ETH_HLEN);
167116f46bf0SSudarsana Reddy Kalluru 
167216f46bf0SSudarsana Reddy Kalluru 	skb = netdev_alloc_skb(edev->ndev, pkt_size);
167316f46bf0SSudarsana Reddy Kalluru 	if (!skb) {
167416f46bf0SSudarsana Reddy Kalluru 		DP_INFO(edev, "Can't allocate skb\n");
167516f46bf0SSudarsana Reddy Kalluru 		rc = -ENOMEM;
167616f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
167716f46bf0SSudarsana Reddy Kalluru 	}
167816f46bf0SSudarsana Reddy Kalluru 	packet = skb_put(skb, pkt_size);
167916f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet, edev->ndev->dev_addr);
168016f46bf0SSudarsana Reddy Kalluru 	ether_addr_copy(packet + ETH_ALEN, edev->ndev->dev_addr);
168116f46bf0SSudarsana Reddy Kalluru 	memset(packet + (2 * ETH_ALEN), 0x77, (ETH_HLEN - (2 * ETH_ALEN)));
168216f46bf0SSudarsana Reddy Kalluru 	for (i = ETH_HLEN; i < pkt_size; i++)
168316f46bf0SSudarsana Reddy Kalluru 		packet[i] = (unsigned char)(i & 0xff);
168416f46bf0SSudarsana Reddy Kalluru 
168516f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_transmit_traffic(edev, skb);
168616f46bf0SSudarsana Reddy Kalluru 	if (rc)
168716f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
168816f46bf0SSudarsana Reddy Kalluru 
168916f46bf0SSudarsana Reddy Kalluru 	rc = qede_selftest_receive_traffic(edev);
169016f46bf0SSudarsana Reddy Kalluru 	if (rc)
169116f46bf0SSudarsana Reddy Kalluru 		goto test_loopback_exit;
169216f46bf0SSudarsana Reddy Kalluru 
169316f46bf0SSudarsana Reddy Kalluru 	DP_VERBOSE(edev, NETIF_MSG_RX_STATUS, "Loopback test successful\n");
169416f46bf0SSudarsana Reddy Kalluru 
169516f46bf0SSudarsana Reddy Kalluru test_loopback_exit:
169616f46bf0SSudarsana Reddy Kalluru 	dev_kfree_skb(skb);
169716f46bf0SSudarsana Reddy Kalluru 
169816f46bf0SSudarsana Reddy Kalluru 	/* Bring up the link in Normal mode */
169916f46bf0SSudarsana Reddy Kalluru 	memset(&link_params, 0, sizeof(link_params));
170016f46bf0SSudarsana Reddy Kalluru 	link_params.link_up = true;
170116f46bf0SSudarsana Reddy Kalluru 	link_params.override_flags = QED_LINK_OVERRIDE_LOOPBACK_MODE;
170216f46bf0SSudarsana Reddy Kalluru 	link_params.loopback_mode = QED_LINK_LOOPBACK_NONE;
170316f46bf0SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &link_params);
170416f46bf0SSudarsana Reddy Kalluru 
170516f46bf0SSudarsana Reddy Kalluru 	/* Wait for loopback configuration to apply */
170616f46bf0SSudarsana Reddy Kalluru 	msleep_interruptible(500);
170716f46bf0SSudarsana Reddy Kalluru 
170816f46bf0SSudarsana Reddy Kalluru 	qede_netif_start(edev);
170916f46bf0SSudarsana Reddy Kalluru 
171016f46bf0SSudarsana Reddy Kalluru 	return rc;
171116f46bf0SSudarsana Reddy Kalluru }
171216f46bf0SSudarsana Reddy Kalluru 
17133044a02eSSudarsana Reddy Kalluru static void qede_self_test(struct net_device *dev,
17143044a02eSSudarsana Reddy Kalluru 			   struct ethtool_test *etest, u64 *buf)
17153044a02eSSudarsana Reddy Kalluru {
17163044a02eSSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
17173044a02eSSudarsana Reddy Kalluru 
17183044a02eSSudarsana Reddy Kalluru 	DP_VERBOSE(edev, QED_MSG_DEBUG,
17193044a02eSSudarsana Reddy Kalluru 		   "Self-test command parameters: offline = %d, external_lb = %d\n",
17203044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_OFFLINE),
17213044a02eSSudarsana Reddy Kalluru 		   (etest->flags & ETH_TEST_FL_EXTERNAL_LB) >> 2);
17223044a02eSSudarsana Reddy Kalluru 
17233044a02eSSudarsana Reddy Kalluru 	memset(buf, 0, sizeof(u64) * QEDE_ETHTOOL_TEST_MAX);
17243044a02eSSudarsana Reddy Kalluru 
172516f46bf0SSudarsana Reddy Kalluru 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
172616f46bf0SSudarsana Reddy Kalluru 		if (qede_selftest_run_loopback(edev,
172716f46bf0SSudarsana Reddy Kalluru 					       QED_LINK_LOOPBACK_INT_PHY)) {
172816f46bf0SSudarsana Reddy Kalluru 			buf[QEDE_ETHTOOL_INT_LOOPBACK] = 1;
172916f46bf0SSudarsana Reddy Kalluru 			etest->flags |= ETH_TEST_FL_FAILED;
173016f46bf0SSudarsana Reddy Kalluru 		}
173116f46bf0SSudarsana Reddy Kalluru 	}
173216f46bf0SSudarsana Reddy Kalluru 
17333044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_interrupt(edev->cdev)) {
17343044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_INTERRUPT_TEST] = 1;
17353044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
17363044a02eSSudarsana Reddy Kalluru 	}
17373044a02eSSudarsana Reddy Kalluru 
17383044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_memory(edev->cdev)) {
17393044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_MEMORY_TEST] = 1;
17403044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
17413044a02eSSudarsana Reddy Kalluru 	}
17423044a02eSSudarsana Reddy Kalluru 
17433044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_register(edev->cdev)) {
17443044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_REGISTER_TEST] = 1;
17453044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
17463044a02eSSudarsana Reddy Kalluru 	}
17473044a02eSSudarsana Reddy Kalluru 
17483044a02eSSudarsana Reddy Kalluru 	if (edev->ops->common->selftest->selftest_clock(edev->cdev)) {
17493044a02eSSudarsana Reddy Kalluru 		buf[QEDE_ETHTOOL_CLOCK_TEST] = 1;
17503044a02eSSudarsana Reddy Kalluru 		etest->flags |= ETH_TEST_FL_FAILED;
17513044a02eSSudarsana Reddy Kalluru 	}
17527a4b21b7SMintz, Yuval 
17537a4b21b7SMintz, Yuval 	if (edev->ops->common->selftest->selftest_nvram(edev->cdev)) {
17547a4b21b7SMintz, Yuval 		buf[QEDE_ETHTOOL_NVRAM_TEST] = 1;
17557a4b21b7SMintz, Yuval 		etest->flags |= ETH_TEST_FL_FAILED;
17567a4b21b7SMintz, Yuval 	}
17573044a02eSSudarsana Reddy Kalluru }
17583044a02eSSudarsana Reddy Kalluru 
17593d789994SManish Chopra static int qede_set_tunable(struct net_device *dev,
17603d789994SManish Chopra 			    const struct ethtool_tunable *tuna,
17613d789994SManish Chopra 			    const void *data)
17623d789994SManish Chopra {
17633d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
17643d789994SManish Chopra 	u32 val;
17653d789994SManish Chopra 
17663d789994SManish Chopra 	switch (tuna->id) {
17673d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
17683d789994SManish Chopra 		val = *(u32 *)data;
17693d789994SManish Chopra 		if (val < QEDE_MIN_PKT_LEN || val > QEDE_RX_HDR_SIZE) {
17703d789994SManish Chopra 			DP_VERBOSE(edev, QED_MSG_DEBUG,
17713d789994SManish Chopra 				   "Invalid rx copy break value, range is [%u, %u]",
17723d789994SManish Chopra 				   QEDE_MIN_PKT_LEN, QEDE_RX_HDR_SIZE);
17733d789994SManish Chopra 			return -EINVAL;
17743d789994SManish Chopra 		}
17753d789994SManish Chopra 
17763d789994SManish Chopra 		edev->rx_copybreak = *(u32 *)data;
17773d789994SManish Chopra 		break;
17783d789994SManish Chopra 	default:
17793d789994SManish Chopra 		return -EOPNOTSUPP;
17803d789994SManish Chopra 	}
17813d789994SManish Chopra 
17823d789994SManish Chopra 	return 0;
17833d789994SManish Chopra }
17843d789994SManish Chopra 
17853d789994SManish Chopra static int qede_get_tunable(struct net_device *dev,
17863d789994SManish Chopra 			    const struct ethtool_tunable *tuna, void *data)
17873d789994SManish Chopra {
17883d789994SManish Chopra 	struct qede_dev *edev = netdev_priv(dev);
17893d789994SManish Chopra 
17903d789994SManish Chopra 	switch (tuna->id) {
17913d789994SManish Chopra 	case ETHTOOL_RX_COPYBREAK:
17923d789994SManish Chopra 		*(u32 *)data = edev->rx_copybreak;
17933d789994SManish Chopra 		break;
17943d789994SManish Chopra 	default:
17953d789994SManish Chopra 		return -EOPNOTSUPP;
17963d789994SManish Chopra 	}
17973d789994SManish Chopra 
17983d789994SManish Chopra 	return 0;
17993d789994SManish Chopra }
18003d789994SManish Chopra 
1801c3dc48f7SSudarsana Reddy Kalluru static int qede_get_eee(struct net_device *dev, struct ethtool_eee *edata)
1802c3dc48f7SSudarsana Reddy Kalluru {
1803c3dc48f7SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1804c3dc48f7SSudarsana Reddy Kalluru 	struct qed_link_output current_link;
1805c3dc48f7SSudarsana Reddy Kalluru 
1806c3dc48f7SSudarsana Reddy Kalluru 	memset(&current_link, 0, sizeof(current_link));
1807c3dc48f7SSudarsana Reddy Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
1808c3dc48f7SSudarsana Reddy Kalluru 
1809c3dc48f7SSudarsana Reddy Kalluru 	if (!current_link.eee_supported) {
1810c3dc48f7SSudarsana Reddy Kalluru 		DP_INFO(edev, "EEE is not supported\n");
1811c3dc48f7SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1812c3dc48f7SSudarsana Reddy Kalluru 	}
1813c3dc48f7SSudarsana Reddy Kalluru 
1814c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.adv_caps & QED_EEE_1G_ADV)
1815c3dc48f7SSudarsana Reddy Kalluru 		edata->advertised = ADVERTISED_1000baseT_Full;
1816c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.adv_caps & QED_EEE_10G_ADV)
1817c3dc48f7SSudarsana Reddy Kalluru 		edata->advertised |= ADVERTISED_10000baseT_Full;
1818c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.sup_caps & QED_EEE_1G_ADV)
1819c3dc48f7SSudarsana Reddy Kalluru 		edata->supported = ADVERTISED_1000baseT_Full;
1820c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.sup_caps & QED_EEE_10G_ADV)
1821c3dc48f7SSudarsana Reddy Kalluru 		edata->supported |= ADVERTISED_10000baseT_Full;
1822c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.lp_adv_caps & QED_EEE_1G_ADV)
1823c3dc48f7SSudarsana Reddy Kalluru 		edata->lp_advertised = ADVERTISED_1000baseT_Full;
1824c3dc48f7SSudarsana Reddy Kalluru 	if (current_link.eee.lp_adv_caps & QED_EEE_10G_ADV)
1825c3dc48f7SSudarsana Reddy Kalluru 		edata->lp_advertised |= ADVERTISED_10000baseT_Full;
1826c3dc48f7SSudarsana Reddy Kalluru 
1827c3dc48f7SSudarsana Reddy Kalluru 	edata->tx_lpi_timer = current_link.eee.tx_lpi_timer;
1828c3dc48f7SSudarsana Reddy Kalluru 	edata->eee_enabled = current_link.eee.enable;
1829c3dc48f7SSudarsana Reddy Kalluru 	edata->tx_lpi_enabled = current_link.eee.tx_lpi_enable;
1830c3dc48f7SSudarsana Reddy Kalluru 	edata->eee_active = current_link.eee_active;
1831c3dc48f7SSudarsana Reddy Kalluru 
1832c3dc48f7SSudarsana Reddy Kalluru 	return 0;
1833c3dc48f7SSudarsana Reddy Kalluru }
1834c3dc48f7SSudarsana Reddy Kalluru 
1835c3dc48f7SSudarsana Reddy Kalluru static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
1836c3dc48f7SSudarsana Reddy Kalluru {
1837c3dc48f7SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
1838c3dc48f7SSudarsana Reddy Kalluru 	struct qed_link_output current_link;
1839c3dc48f7SSudarsana Reddy Kalluru 	struct qed_link_params params;
1840c3dc48f7SSudarsana Reddy Kalluru 
1841c3dc48f7SSudarsana Reddy Kalluru 	if (!edev->ops->common->can_link_change(edev->cdev)) {
1842c3dc48f7SSudarsana Reddy Kalluru 		DP_INFO(edev, "Link settings are not allowed to be changed\n");
1843c3dc48f7SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1844c3dc48f7SSudarsana Reddy Kalluru 	}
1845c3dc48f7SSudarsana Reddy Kalluru 
1846c3dc48f7SSudarsana Reddy Kalluru 	memset(&current_link, 0, sizeof(current_link));
1847c3dc48f7SSudarsana Reddy Kalluru 	edev->ops->common->get_link(edev->cdev, &current_link);
1848c3dc48f7SSudarsana Reddy Kalluru 
1849c3dc48f7SSudarsana Reddy Kalluru 	if (!current_link.eee_supported) {
1850c3dc48f7SSudarsana Reddy Kalluru 		DP_INFO(edev, "EEE is not supported\n");
1851c3dc48f7SSudarsana Reddy Kalluru 		return -EOPNOTSUPP;
1852c3dc48f7SSudarsana Reddy Kalluru 	}
1853c3dc48f7SSudarsana Reddy Kalluru 
1854c3dc48f7SSudarsana Reddy Kalluru 	memset(&params, 0, sizeof(params));
1855c3dc48f7SSudarsana Reddy Kalluru 	params.override_flags |= QED_LINK_OVERRIDE_EEE_CONFIG;
1856c3dc48f7SSudarsana Reddy Kalluru 
1857c3dc48f7SSudarsana Reddy Kalluru 	if (!(edata->advertised & (ADVERTISED_1000baseT_Full |
1858c3dc48f7SSudarsana Reddy Kalluru 				   ADVERTISED_10000baseT_Full)) ||
1859c3dc48f7SSudarsana Reddy Kalluru 	    ((edata->advertised & (ADVERTISED_1000baseT_Full |
1860c3dc48f7SSudarsana Reddy Kalluru 				   ADVERTISED_10000baseT_Full)) !=
1861c3dc48f7SSudarsana Reddy Kalluru 	     edata->advertised)) {
1862c3dc48f7SSudarsana Reddy Kalluru 		DP_VERBOSE(edev, QED_MSG_DEBUG,
1863c3dc48f7SSudarsana Reddy Kalluru 			   "Invalid advertised capabilities %d\n",
1864c3dc48f7SSudarsana Reddy Kalluru 			   edata->advertised);
1865c3dc48f7SSudarsana Reddy Kalluru 		return -EINVAL;
1866c3dc48f7SSudarsana Reddy Kalluru 	}
1867c3dc48f7SSudarsana Reddy Kalluru 
1868c3dc48f7SSudarsana Reddy Kalluru 	if (edata->advertised & ADVERTISED_1000baseT_Full)
1869c3dc48f7SSudarsana Reddy Kalluru 		params.eee.adv_caps = QED_EEE_1G_ADV;
1870c3dc48f7SSudarsana Reddy Kalluru 	if (edata->advertised & ADVERTISED_10000baseT_Full)
1871c3dc48f7SSudarsana Reddy Kalluru 		params.eee.adv_caps |= QED_EEE_10G_ADV;
1872c3dc48f7SSudarsana Reddy Kalluru 	params.eee.enable = edata->eee_enabled;
1873c3dc48f7SSudarsana Reddy Kalluru 	params.eee.tx_lpi_enable = edata->tx_lpi_enabled;
1874c3dc48f7SSudarsana Reddy Kalluru 	params.eee.tx_lpi_timer = edata->tx_lpi_timer;
1875c3dc48f7SSudarsana Reddy Kalluru 
1876c3dc48f7SSudarsana Reddy Kalluru 	params.link_up = true;
1877c3dc48f7SSudarsana Reddy Kalluru 	edev->ops->common->set_link(edev->cdev, &params);
1878c3dc48f7SSudarsana Reddy Kalluru 
1879c3dc48f7SSudarsana Reddy Kalluru 	return 0;
1880c3dc48f7SSudarsana Reddy Kalluru }
1881c3dc48f7SSudarsana Reddy Kalluru 
188297df0d65SSudarsana Reddy Kalluru static int qede_get_module_info(struct net_device *dev,
188397df0d65SSudarsana Reddy Kalluru 				struct ethtool_modinfo *modinfo)
188497df0d65SSudarsana Reddy Kalluru {
188597df0d65SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
188697df0d65SSudarsana Reddy Kalluru 	u8 buf[4];
188797df0d65SSudarsana Reddy Kalluru 	int rc;
188897df0d65SSudarsana Reddy Kalluru 
188997df0d65SSudarsana Reddy Kalluru 	/* Read first 4 bytes to find the sfp type */
189097df0d65SSudarsana Reddy Kalluru 	rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
189197df0d65SSudarsana Reddy Kalluru 						   QED_I2C_DEV_ADDR_A0, 0, 4);
189297df0d65SSudarsana Reddy Kalluru 	if (rc) {
189397df0d65SSudarsana Reddy Kalluru 		DP_ERR(edev, "Failed reading EEPROM data %d\n", rc);
189497df0d65SSudarsana Reddy Kalluru 		return rc;
189597df0d65SSudarsana Reddy Kalluru 	}
189697df0d65SSudarsana Reddy Kalluru 
189797df0d65SSudarsana Reddy Kalluru 	switch (buf[0]) {
189897df0d65SSudarsana Reddy Kalluru 	case 0x3: /* SFP, SFP+, SFP-28 */
189997df0d65SSudarsana Reddy Kalluru 		modinfo->type = ETH_MODULE_SFF_8472;
190097df0d65SSudarsana Reddy Kalluru 		modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
190197df0d65SSudarsana Reddy Kalluru 		break;
190297df0d65SSudarsana Reddy Kalluru 	case 0xc: /* QSFP */
190397df0d65SSudarsana Reddy Kalluru 	case 0xd: /* QSFP+ */
190497df0d65SSudarsana Reddy Kalluru 		modinfo->type = ETH_MODULE_SFF_8436;
190597df0d65SSudarsana Reddy Kalluru 		modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
190697df0d65SSudarsana Reddy Kalluru 		break;
190797df0d65SSudarsana Reddy Kalluru 	case 0x11: /* QSFP-28 */
190897df0d65SSudarsana Reddy Kalluru 		modinfo->type = ETH_MODULE_SFF_8636;
190997df0d65SSudarsana Reddy Kalluru 		modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
191097df0d65SSudarsana Reddy Kalluru 		break;
191197df0d65SSudarsana Reddy Kalluru 	default:
191297df0d65SSudarsana Reddy Kalluru 		DP_ERR(edev, "Unknown transceiver type 0x%x\n", buf[0]);
191397df0d65SSudarsana Reddy Kalluru 		return -EINVAL;
191497df0d65SSudarsana Reddy Kalluru 	}
191597df0d65SSudarsana Reddy Kalluru 
191697df0d65SSudarsana Reddy Kalluru 	return 0;
191797df0d65SSudarsana Reddy Kalluru }
191897df0d65SSudarsana Reddy Kalluru 
191997df0d65SSudarsana Reddy Kalluru static int qede_get_module_eeprom(struct net_device *dev,
192097df0d65SSudarsana Reddy Kalluru 				  struct ethtool_eeprom *ee, u8 *data)
192197df0d65SSudarsana Reddy Kalluru {
192297df0d65SSudarsana Reddy Kalluru 	struct qede_dev *edev = netdev_priv(dev);
192397df0d65SSudarsana Reddy Kalluru 	u32 start_addr = ee->offset, size = 0;
192497df0d65SSudarsana Reddy Kalluru 	u8 *buf = data;
192597df0d65SSudarsana Reddy Kalluru 	int rc = 0;
192697df0d65SSudarsana Reddy Kalluru 
192797df0d65SSudarsana Reddy Kalluru 	/* Read A0 section */
192897df0d65SSudarsana Reddy Kalluru 	if (ee->offset < ETH_MODULE_SFF_8079_LEN) {
192997df0d65SSudarsana Reddy Kalluru 		/* Limit transfer size to the A0 section boundary */
193097df0d65SSudarsana Reddy Kalluru 		if (ee->offset + ee->len > ETH_MODULE_SFF_8079_LEN)
193197df0d65SSudarsana Reddy Kalluru 			size = ETH_MODULE_SFF_8079_LEN - ee->offset;
193297df0d65SSudarsana Reddy Kalluru 		else
193397df0d65SSudarsana Reddy Kalluru 			size = ee->len;
193497df0d65SSudarsana Reddy Kalluru 
193597df0d65SSudarsana Reddy Kalluru 		rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
193697df0d65SSudarsana Reddy Kalluru 							   QED_I2C_DEV_ADDR_A0,
193797df0d65SSudarsana Reddy Kalluru 							   start_addr, size);
193897df0d65SSudarsana Reddy Kalluru 		if (rc) {
193997df0d65SSudarsana Reddy Kalluru 			DP_ERR(edev, "Failed reading A0 section  %d\n", rc);
194097df0d65SSudarsana Reddy Kalluru 			return rc;
194197df0d65SSudarsana Reddy Kalluru 		}
194297df0d65SSudarsana Reddy Kalluru 
194397df0d65SSudarsana Reddy Kalluru 		buf += size;
194497df0d65SSudarsana Reddy Kalluru 		start_addr += size;
194597df0d65SSudarsana Reddy Kalluru 	}
194697df0d65SSudarsana Reddy Kalluru 
194797df0d65SSudarsana Reddy Kalluru 	/* Read A2 section */
194897df0d65SSudarsana Reddy Kalluru 	if (start_addr >= ETH_MODULE_SFF_8079_LEN &&
194997df0d65SSudarsana Reddy Kalluru 	    start_addr < ETH_MODULE_SFF_8472_LEN) {
195097df0d65SSudarsana Reddy Kalluru 		size = ee->len - size;
195197df0d65SSudarsana Reddy Kalluru 		/* Limit transfer size to the A2 section boundary */
195297df0d65SSudarsana Reddy Kalluru 		if (start_addr + size > ETH_MODULE_SFF_8472_LEN)
195397df0d65SSudarsana Reddy Kalluru 			size = ETH_MODULE_SFF_8472_LEN - start_addr;
195497df0d65SSudarsana Reddy Kalluru 		start_addr -= ETH_MODULE_SFF_8079_LEN;
195597df0d65SSudarsana Reddy Kalluru 		rc = edev->ops->common->read_module_eeprom(edev->cdev, buf,
195697df0d65SSudarsana Reddy Kalluru 							   QED_I2C_DEV_ADDR_A2,
195797df0d65SSudarsana Reddy Kalluru 							   start_addr, size);
195897df0d65SSudarsana Reddy Kalluru 		if (rc) {
195997df0d65SSudarsana Reddy Kalluru 			DP_VERBOSE(edev, QED_MSG_DEBUG,
196097df0d65SSudarsana Reddy Kalluru 				   "Failed reading A2 section %d\n", rc);
196197df0d65SSudarsana Reddy Kalluru 			return 0;
196297df0d65SSudarsana Reddy Kalluru 		}
196397df0d65SSudarsana Reddy Kalluru 	}
196497df0d65SSudarsana Reddy Kalluru 
196597df0d65SSudarsana Reddy Kalluru 	return rc;
196697df0d65SSudarsana Reddy Kalluru }
196797df0d65SSudarsana Reddy Kalluru 
1968133fac0eSSudarsana Kalluru static const struct ethtool_ops qede_ethtool_ops = {
1969054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
1970054c67d1SSudarsana Reddy Kalluru 	.set_link_ksettings = qede_set_link_ksettings,
1971133fac0eSSudarsana Kalluru 	.get_drvinfo = qede_get_drvinfo,
1972e0971c83STomer Tayar 	.get_regs_len = qede_get_regs_len,
1973e0971c83STomer Tayar 	.get_regs = qede_get_regs,
197414d39648SMintz, Yuval 	.get_wol = qede_get_wol,
197514d39648SMintz, Yuval 	.set_wol = qede_set_wol,
1976133fac0eSSudarsana Kalluru 	.get_msglevel = qede_get_msglevel,
1977133fac0eSSudarsana Kalluru 	.set_msglevel = qede_set_msglevel,
197832a7a570SSudarsana Kalluru 	.nway_reset = qede_nway_reset,
1979133fac0eSSudarsana Kalluru 	.get_link = qede_get_link,
1980d552fa84SSudarsana Reddy Kalluru 	.get_coalesce = qede_get_coalesce,
1981d552fa84SSudarsana Reddy Kalluru 	.set_coalesce = qede_set_coalesce,
198201ef7e05SSudarsana Kalluru 	.get_ringparam = qede_get_ringparam,
198301ef7e05SSudarsana Kalluru 	.set_ringparam = qede_set_ringparam,
19840f7db144SSudarsana Kalluru 	.get_pauseparam = qede_get_pauseparam,
19850f7db144SSudarsana Kalluru 	.set_pauseparam = qede_set_pauseparam,
1986133fac0eSSudarsana Kalluru 	.get_strings = qede_get_strings,
19873d971cbdSSudarsana Kalluru 	.set_phys_id = qede_set_phys_id,
1988133fac0eSSudarsana Kalluru 	.get_ethtool_stats = qede_get_ethtool_stats,
1989f3e72109SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
1990133fac0eSSudarsana Kalluru 	.get_sset_count = qede_get_sset_count,
1991961acdeaSSudarsana Reddy Kalluru 	.get_rxnfc = qede_get_rxnfc,
1992961acdeaSSudarsana Reddy Kalluru 	.set_rxnfc = qede_set_rxnfc,
1993961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
1994961acdeaSSudarsana Reddy Kalluru 	.get_rxfh_key_size = qede_get_rxfh_key_size,
1995961acdeaSSudarsana Reddy Kalluru 	.get_rxfh = qede_get_rxfh,
1996961acdeaSSudarsana Reddy Kalluru 	.set_rxfh = qede_set_rxfh,
19974c55215cSSudarsana Reddy Kalluru 	.get_ts_info = qede_get_ts_info,
19988edf049dSSudarsana Kalluru 	.get_channels = qede_get_channels,
19998edf049dSSudarsana Kalluru 	.set_channels = qede_set_channels,
20003044a02eSSudarsana Reddy Kalluru 	.self_test = qede_self_test,
200197df0d65SSudarsana Reddy Kalluru 	.get_module_info = qede_get_module_info,
200297df0d65SSudarsana Reddy Kalluru 	.get_module_eeprom = qede_get_module_eeprom,
2003c3dc48f7SSudarsana Reddy Kalluru 	.get_eee = qede_get_eee,
2004c3dc48f7SSudarsana Reddy Kalluru 	.set_eee = qede_set_eee,
2005c3dc48f7SSudarsana Reddy Kalluru 
20063d789994SManish Chopra 	.get_tunable = qede_get_tunable,
20073d789994SManish Chopra 	.set_tunable = qede_set_tunable,
2008ccfa110cSSudarsana Reddy Kalluru 	.flash_device = qede_flash_device,
2009133fac0eSSudarsana Kalluru };
2010133fac0eSSudarsana Kalluru 
2011fefb0202SYuval Mintz static const struct ethtool_ops qede_vf_ethtool_ops = {
2012054c67d1SSudarsana Reddy Kalluru 	.get_link_ksettings = qede_get_link_ksettings,
2013fefb0202SYuval Mintz 	.get_drvinfo = qede_get_drvinfo,
2014fefb0202SYuval Mintz 	.get_msglevel = qede_get_msglevel,
2015fefb0202SYuval Mintz 	.set_msglevel = qede_set_msglevel,
2016fefb0202SYuval Mintz 	.get_link = qede_get_link,
2017477f2d14SRahul Verma 	.get_coalesce = qede_get_coalesce,
2018477f2d14SRahul Verma 	.set_coalesce = qede_set_coalesce,
2019fefb0202SYuval Mintz 	.get_ringparam = qede_get_ringparam,
2020fefb0202SYuval Mintz 	.set_ringparam = qede_set_ringparam,
2021fefb0202SYuval Mintz 	.get_strings = qede_get_strings,
2022fefb0202SYuval Mintz 	.get_ethtool_stats = qede_get_ethtool_stats,
2023fefb0202SYuval Mintz 	.get_priv_flags = qede_get_priv_flags,
2024fefb0202SYuval Mintz 	.get_sset_count = qede_get_sset_count,
2025fefb0202SYuval Mintz 	.get_rxnfc = qede_get_rxnfc,
2026fefb0202SYuval Mintz 	.set_rxnfc = qede_set_rxnfc,
2027fefb0202SYuval Mintz 	.get_rxfh_indir_size = qede_get_rxfh_indir_size,
2028fefb0202SYuval Mintz 	.get_rxfh_key_size = qede_get_rxfh_key_size,
2029fefb0202SYuval Mintz 	.get_rxfh = qede_get_rxfh,
2030fefb0202SYuval Mintz 	.set_rxfh = qede_set_rxfh,
2031fefb0202SYuval Mintz 	.get_channels = qede_get_channels,
2032fefb0202SYuval Mintz 	.set_channels = qede_set_channels,
20333d789994SManish Chopra 	.get_tunable = qede_get_tunable,
20343d789994SManish Chopra 	.set_tunable = qede_set_tunable,
2035fefb0202SYuval Mintz };
2036fefb0202SYuval Mintz 
2037133fac0eSSudarsana Kalluru void qede_set_ethtool_ops(struct net_device *dev)
2038133fac0eSSudarsana Kalluru {
2039fefb0202SYuval Mintz 	struct qede_dev *edev = netdev_priv(dev);
2040fefb0202SYuval Mintz 
2041fefb0202SYuval Mintz 	if (IS_VF(edev))
2042fefb0202SYuval Mintz 		dev->ethtool_ops = &qede_vf_ethtool_ops;
2043fefb0202SYuval Mintz 	else
2044133fac0eSSudarsana Kalluru 		dev->ethtool_ops = &qede_ethtool_ops;
2045133fac0eSSudarsana Kalluru }
2046